当前位置: 首页 > news >正文

若依系统(Security)增加微信小程序登录(自定义登录)

若依系统(分离版后端)自带的账号验证是基于 

UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);

验证,然后在系统中controller或service类中 SecurityUtils 工具类中直接可获取用户或用户ID等

SecurityUtils.getLoginUser().getUser();

现在想实现,微信小程序通过code等登录后返回和之前一样的token后原逻辑中的SecurityUtils一样可以获取到,则需要自定义扩展登录类。废话不多说,上代码:

类似于UsernamePasswordAuthenticationToken类,自定义AuthCodeAuthenticationToken.java

在这个位置:

AuthCodeAuthenticationToken.java:

package com.ruoyi.framework;import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;import java.util.Collection;public class AuthCodeAuthenticationToken extends AbstractAuthenticationToken {private final Object principal;public AuthCodeAuthenticationToken(Object principal) {super(null);this.principal= principal;}public AuthCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {super(authorities);this.principal= principal;super.setAuthenticated(true);}@Overridepublic Object getCredentials() {return null;}@Overridepublic Object getPrincipal() {return this.principal;}@Overridepublic void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {if (isAuthenticated) {throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");}super.setAuthenticated(false);}
}
AuthCodeAuthenticationProvider.java
package com.ruoyi.framework;import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;public class AuthCodeAuthenticationProvider implements AuthenticationProvider {private UserDetailsService userDetailsService;public AuthCodeAuthenticationProvider(UserDetailsService userDetailsService) {setUserDetailsService(userDetailsService);}@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {AuthCodeAuthenticationToken authCodeAuthenticationToken = (AuthCodeAuthenticationToken) authentication;String telephone = (String) authentication.getPrincipal();UserDetails userDetails = userDetailsService.loadUserByUsername(telephone);AuthCodeAuthenticationToken authenticationResult = new AuthCodeAuthenticationToken(userDetails, userDetails.getAuthorities());authenticationResult.setDetails(authentication.getDetails());return authenticationResult;}@Overridepublic boolean supports(Class<?> authentication) {return AuthCodeAuthenticationToken.class.isAssignableFrom(authentication);}public UserDetailsService getUserDetailsService() {return userDetailsService;}public void setUserDetailsService(UserDetailsService userDetailsService) {this.userDetailsService = userDetailsService;}
}
在这里还要重写UserDetailsServiceByAuthCodeImpl.java原逻辑是调用的UserDetailsServiceImpl.java中的loadUserByUsername方法。
package com.ruoyi.framework.web.service;import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;@Slf4j
@Service("userDetailsByAuthCode")
public class UserDetailsServiceByAuthCodeImpl implements UserDetailsService {@Autowiredprivate ISysUserService userService;@Autowiredprivate SysPermissionService permissionService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{SysUser user = userService.selectUserByUserName(username);if (StringUtils.isNull(user)){log.info("登录用户:{} 不存在.", username);throw new ServiceException(MessageUtils.message("user.not.exists"));}else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())){log.info("登录用户:{} 已被删除.", username);throw new ServiceException(MessageUtils.message("user.password.delete"));}else if (UserStatus.DISABLE.getCode().equals(user.getStatus())){log.info("登录用户:{} 已被停用.", username);throw new ServiceException(MessageUtils.message("user.blocked"));}return createLoginUser(user);}public UserDetails createLoginUser(SysUser user){return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));}
}

在SecurityConfig.java中配置自定义的登录逻辑(顶部注入,下面增加配置)

配置中api开头的接口,该放开(登录获取token的接口)的放开:

温馨提示:一定要区分原来的UserDetailsService 使用注解@Qualifier("userDetailsByAuthCode")区分,原来的也要加上,不然启动时候注入重复,原来的serviceImpl实现类也要加上,如下:

SysLoginService.java中
public String wxLogin(String userName){// 用户验证Authentication authentication = null;try{AuthCodeAuthenticationToken authCodeAuthenticationToken = new AuthCodeAuthenticationToken(userName);AuthenticationContextHolder.setContext(authCodeAuthenticationToken);// 该方法会去调用UserDetailsServiceImpl.loadUserByUsernameauthentication = authenticationManager.authenticate(authCodeAuthenticationToken);}catch (Exception e){if (e instanceof BadCredentialsException){AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}else{AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}}finally{AuthenticationContextHolder.clearContext();}AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());// 生成tokenreturn tokenService.createToken(loginUser);}

接口调用中可以如下调用了:

相关文章:

若依系统(Security)增加微信小程序登录(自定义登录)

若依系统(分离版后端)自带的账号验证是基于 UsernamePasswordAuthenticationToken authenticationToken new UsernamePasswordAuthenticationToken(username, password); 验证&#xff0c;然后在系统中controller或service类中 SecurityUtils 工具类中直接可获取用户或用户…...

道可云人工智能元宇宙每日资讯|2024互联网岳麓峰会在长沙召开

道可云元宇宙每日简报&#xff08;2024年9月10日&#xff09;讯&#xff0c;今日元宇宙新鲜事有&#xff1a; 2024互联网岳麓峰会在长沙召开 9月9日&#xff0c;2024互联网岳麓峰会在长沙召开&#xff0c;湖南省副省长曹志强在峰会表示&#xff0c;今年上半年湖南省人工智能产…...

MySQL JDBC URL各参数详解

jdbc:mysql://localhost:3306/test?userroot&password123456&useUnicodetrue&characterEncodinggbk &autoReconnecttrue&failOverReadOnlyfalse&serverTimezoneUTC&drivercom.mysql.cj.jdbc.Driver 参数名称参数说明缺省值user指定用于连接数据库…...

celery control.shutdown

Celery 提供了 control 模块&#xff0c;允许你发送控制命令给正在运行的 worker。其中 shutdown 命令可以用来关闭一个或多个 worker。下面是如何使用 control.shutdown 来关闭 worker 的详细说明。 使用 control.shutdown 1. 导入必要的模块 首先&#xff0c;你需要导入 C…...

数据库设计与软件工程阶段的对应关系

数据库设计的很多阶段确实可以与软件工程的各阶段对应起来&#xff0c;这体现了数据库设计作为软件工程中一个核心组成部分的紧密关联性。 1. 需求分析阶段 数据库设计&#xff1a;需求分析是数据库设计的初始阶段&#xff0c;主要任务是收集和分析用户的需求&#xff0c;包括…...

基于ASP+ACCESS的教师信息管理系统

摘要 随着我国社会主义市场经济的发展和改革开放的不断深入&#xff0c;计算机的应用已遍及国民经济的各个领域&#xff0c;计算机来到我们的工作和生活中&#xff0c;改变着我们和周围的一切。在以前&#xff0c;学校用手工处理教师档案以及工资发放等繁多的工作和数据时&…...

【智能体】浅谈大模型之AI Agent

随着ChatGPT推出插件和函数调用功能&#xff0c;构建以LLM&#xff08;大语言模型&#xff09;为核心控制器的AI Agent愈发成为一个拥有无限可能的概念。 AI Agent是一种超越简单文本生成的人工智能系统。它使用大型语言模型&#xff08;LLM&#xff09;作为其核心计算引擎&am…...

大疆 嵌入式 笔记 面试题目汇总大全[嵌入式找工作必看] 比较有难度适合进阶收藏学习

24届大疆车载嵌入式系统安全面试经验 投递岗位&#xff1a;&#xff08;大疆车载&#xff09;嵌入式系统安全 投递时间&#xff1a;大疆大概在7月-8月月初开秋招岗位。8月月中开始笔试&#xff0c;8月月末开始面试。&#xff08;理论上9月&#xff0c;10月开奖。&#xff09;…...

线程池以及详解使用@Async注解异步处理方法

目录 一.什么是线程池&#xff1a; 二.使用线程池的好处&#xff1a; 三.线程池的使用场景&#xff1a; 四.使用线程池来提高Springboot项目的并发处理能力&#xff1a; 1.在application.yml配置文件中配置&#xff1a; 2.定义配置类来接受配置文件内的属性值&#xff1a…...

css鼠标移动过去变成手的图标

在css中定义 cursor:pointer;直接在html中指定 <div class"mt-2 mt-md-2 mt-lg-1 fs-md-1 fs-lg-2 " style"cursor:pointer;"></div>...

uniapp 懒加载、预加载、缓存机制深度解析

uniapp 懒加载、预加载、缓存机制深度解析 文章目录 uniapp 懒加载、预加载、缓存机制深度解析一、为什么要使用uniapp的懒加载、预加载和缓存机制二、如何使用uniapp的懒加载、预加载和缓存机制1. 懒加载2. 预加载3. 缓存机制 四、扩展与高级技巧1. 结合懒加载和预加载优化页面…...

《OpenCV计算机视觉》—— 图像形态学(腐蚀、膨胀等)

文章目录 一、图像形态学基本概念二、基本运算1.简单介绍2.代码实现 三、高级运算1.简单介绍2.代码实现 一、图像形态学基本概念 图像形态学是图像处理科学的一个独立分支&#xff0c;它基于集合论和数学形态学的理论&#xff0c;专门用于分析和处理图像中的形状和结构。图像形…...

【Rust光年纪】海洋学研究的利器:Rust语言海洋学计算库详解

探索Rust语言下的海洋学计算库&#xff1a;功能对比与选择指南 前言 随着科学技术的不断发展&#xff0c;海洋学领域对于计算和数据处理的需求也日益增长。在Rust语言中&#xff0c;出现了一系列专注于海洋学计算和数据处理的库&#xff0c;它们为海洋学工作者提供了强大的工…...

Word文档的读入【2】

现在&#xff0c;乔老师已经了解了Word文档的基本结构。 下面&#xff0c;我们通过观察一份答题卡来思考一下每条信息的具体位置。这样&#xff0c;在后面几天的学习和操作中&#xff0c;我们就能更快、更准确地读取到答题卡中的信息。 这份答题卡是由一个表格和一些段落组成。…...

报名开启 | 游戏开发缺队友?首期繁星招聘会来袭!

**点击蓝链领取游戏开发教程 ** EE GAMES 创作者社区是专注于链接每一位游戏创作者&#xff0c;提供社区交流、团队匹配、经验共享、成果展示、知识整合、最新活动资讯等全方位服务的游戏领域垂类社区。 这里不仅仅是一个游戏创作的互助平台&#xff0c;更是每一位游戏创作者…...

无法加载源https://api.nuget.org/v3/index.json的服务索引

我是用的visual studio2022 17.11.2版本&#xff0c;在运行.net c#项目的时候显示“无法加载源https://api.nuget.org/v3/index.json的服务索引”&#xff0c;从网上找了一堆方法全部没用&#xff0c;最后用这个方法解决了。亲测有效家人们 关闭VS&#xff0c;删除C:\Users\xx…...

C#--CM+Fody+HCWPF开发组合

CM&#xff1a;Caliburn.Micro(简称CM)一经推出便备受推崇&#xff0c;作为一款MVVM开发模式的经典框架&#xff0c;越来越多的受到wpf开发者的青睐.我们看一下官方的描述&#xff1a;Caliburn是一个为Xaml平台设计的小型但功能强大的框架。Micro实现了各种UI模式&#xff0c;用…...

力扣474-一和零(Java详细题解)

题目链接&#xff1a;474. 一和零 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完01背包&#xff0c;所以现在的题解都是以01背包问题为基础再来写的。 如果大家不懂01背包的话&#…...

【话题】量子计算:前沿技术与应用前景深度解析

引言 在当今信息时代&#xff0c;计算能力已成为推动科技进步和社会发展的重要驱动力。随着摩尔定律逐渐接近其物理极限&#xff0c;传统计算机硬件的性能提升面临前所未有的挑战。在此背景下&#xff0c;量子计算作为一种革命性的计算范式&#xff0c;凭借其独特的量子力学属性…...

第11章 32位x86处理器编程架构

第11章 32位x86处理器编程架构 IA-32(INTEL Architecture, 32-bit)&#xff1a;INTEL 32位处理器架构简称IA-3&#xff0c;以8086处理器为基础发展起来的。该章重点介绍了IA-32处理器的工作方式和相关技术。 IA-32架构的基本执行环境 寄存器的扩展 32位处理器通用寄存器&am…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...