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

news2024/11/14 20:06:32

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

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);
    }



    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    public 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);
    }

    @Override
    public 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;
    }

    @Override
    public 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 {

    @Autowired
    private ISysUserService userService;

    @Autowired
    private SysPermissionService permissionService;
    @Override
    public 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.loadUserByUsername
            authentication = 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());
        // 生成token
        return tokenService.createToken(loginUser);
    }

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2122243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PowerShell下载文件的5种简单方法,总有一种适合你

序言 PowerShell是一个功能强大的工具,不仅适用于IT专业人员,如果你想自动化任务或下载文件,它也能做得到。如果你想快速、可靠地从互联网上抓取文件,它们非常有用。以下是使用PowerShell下载文件的最简单方法。 使用Invoke WebRequest下载 使用PowerShell下载文件的最简…

如何查询、统计品牌在抖音的品牌声量?

现在抖音平台的竞争越来越激烈&#xff0c;企业想做好在抖音平台上的品牌营销&#xff0c;就需要时刻监测抖音上品牌声量的大小&#xff0c;比如企业品牌声量趋势、品牌sov值、搜索指数等相关指标&#xff0c;辅助衡量品牌宣传效果如何。那怎么去查询统计品牌声量情况呢&#x…

用于完善智能电表设计的 FPGA 到 ASIC 研究

许多嵌入式系统设计首先使用 FPGA 来实现。这可能是为了更快地进行原型设计或提供软件开发平台。有时&#xff0c;生产开始后&#xff0c;FPGA 仍保留在设计中。但通常情况下&#xff0c;计划是将 FPGA&#xff08;或多个 FPGA&#xff09;转换为 ASIC 以进行批量制造。 人们很…

万龙觉醒免费辅助:VMOS云手机多开攻略!黄金圣殿攻略详情!

在《万龙觉醒》的世界中&#xff0c;玩家将迎来诸多挑战&#xff0c;而其中最具策略性的活动之一便是黄金圣殿的征战。为了让玩家能够轻松应对游戏中的难题&#xff0c;我们强烈推荐使用VMOS云手机。VMOS云手机不仅针对《万龙觉醒》推出了专属定制版云手机&#xff0c;内置游戏…

vue如何使用百度地图

一、引入百度地图 1.public文件夹下放置index.html文件 2.在html文件中引入网址&#xff0c; 二、在config.js文件中添加externals.BMap配置&#xff0c;与entry平级&#xff0c;内容如下 三、设置地图区域 必须设置div宽度和高度&#xff0c;否则也不能正常显…

记一次H5应用轻量优化方案调研与实施

由于H5应用具备开发周期短、灵活性好的特点,所以OA项目应用功能开发过程中经常结合WebView +H5进行Hybrid模式开发,但Android 原生WebView客观存在的性能问题,导致H5应用加载速度慢,影响用户体验。基于OA H5应用中找到审批详情加载慢的原因,并对其优化。 一个页面在WebVi…

快手怎么关闭ip地址 抖音ip属地如何隐藏

快手怎么关闭ip地址 要在快手上关闭IP地址的显示&#xff0c;您可以通过以下步骤来操作&#xff0c;以保护您的隐私&#xff1a; ‌打开快手APP‌&#xff1a;首先&#xff0c;确保您已经安装了快手APP&#xff0c;并且处于登录状态。 ‌进入设置页面‌&#xff1a;在快手AP…

2024骨传导耳机哪个牌子好?分享五款资深用户好评的骨传导耳机!

随着骨传导耳机市场的稳步增长&#xff0c;消费者群体日益扩大&#xff0c;对使用安全与品质的关注也随之提升。值得注意的是&#xff0c;市场上涌现出不少由非专业制造商贴牌或网络红人推广的骨传导耳机产品&#xff0c;这些产品往往因缺乏深厚的技术底蕴与精细的音质调校&…

聚类案例——汽车是否值得购买

对汽车是否值得购买&#xff0c;进行聚类分析&#xff1a; 1、数据指标解释&#xff1a; buying, 购买费用 maint, 维修费用 doors, 车门数量 person, 乘坐人数 lug_boot, 行李箱容量 safety, 安全性 2、对数据进行转换 将字符串转换映射量化为数字 数据加载&#xff1a…

编程珠玑3-8

问题 8.[S.C.Johnnson]七段显示设备实现十进制数字&#xff1a; 的廉价显示。七段显示通常如下编号&#xff1a; 编写一个使用5个七段显示数字来显示16位正整数的程序。输出为一个5个字节的数组&#xff0c;当且仅当数字j中的第i段点亮时&#xff0c;字节j中的位i置1 分析 简…

Mac视频vedio转成gif图

方法一&#xff1a;系统自带&#xff1a;Keynote 1、用"Keynote"创建幻灯片。 2、把视频拖拽进入。 3、Keynote右上角有个“文稿”&#xff0c;点击调整幻灯片大小。&#xff08;坑点&#xff1a;按比例调整&#xff09; 4、文件 -> 导出为“Gif动画”。 方法…

TDesign:腾讯的开源企业级前端框架,能和ant-design一战吗?

TDesign 是一套拥有完整的 设计价值观 和 视觉风格指南 的企业级设计体系&#xff0c;同时提供了丰富的 设计资源。TDesign 在设计体系基础上产出基于 Vue、React、小程序等业界主流技术栈的组件库解决方案。是不是有点晚了&#xff1f; 请大家各抒己见。

【开源大模型生态7】华为的盘古大模型

鹏程盘古模型是全球首个全开源2000亿参数的自回归中文预训练语言大模型&#xff0c;在知识问答、知识检索、知识推理、阅读理解等文本生成领域表现突出。 2070亿参数&#xff0c;64层。 这里注意几个概念。 参数&#xff08;Parameters&#xff09;&#xff1a; 参数是指构成模…

K8s中如何使用etcd进行集群信息的备份与恢复

这里写目录标题 ETCD是什么?1. **`etcd`(服务)**2. **`etcdctl`(客户端工具)**如何安装etcdctl(客户端工具)查看目前K8s自带etcd中的版本信息安装对应版本的etcdutl工具下载 `etcdutl` 3.5.7 版本配置环境变量创建备份文件验证一下备份的快照文件备份文件恢复的效果演示…

MmAP(论文解读) : Multi-Modal Alignment Prompt for Cross-Domain Multi-Task Learning

MmAP&#xff1a;跨领域多任务学习的多模态提示对齐 AAAI 2024 摘要 多任务学习&#xff08;Multi-Task Learning&#xff0c;MTL&#xff09;同时训练多个相关的任务&#xff0c;从而能够提高单个任务的性能。通常&#xff0c;一个多任务网络架构包含共享backbone和任务特定…

根据NVeloDocx Word模板引擎生成Word(三)

基于永久免费开放的《E6低代码开发平台》的Word模版引擎NVeloDocx&#xff0c;实现根据Word模版生成Word文件&#xff0c;前面2篇已经非常详细介绍了《主表单字段》&#xff0c;《子表记录循环输入到表格》。那这一篇我们就介绍插入单张图片、二维码&#xff0c;条形码等等&…

区块链媒体:区块链媒体套餐倾心推广解析!

塞翁失马&#xff0c;区块链媒体套餐&#xff0c;两者看似毫不相干&#xff0c;实际上却反映了区块链技术的广泛运用和媒体领域的创新模式。本文将带你深入了解这一新兴领域的背后故事&#xff0c;并分析区块链媒体套餐推广的关键因素。 塞翁失马的寓意 塞翁失马是中国古代的一…

实例讲解电动汽车车速计算算法及Simulink建模方法

电动汽车的车速信号是一个非常重要的信号&#xff0c;在VCU软件开发中&#xff0c;车速一般需要通过采集其他控制器车速或者通过电机转速间接计算出来&#xff0c;作为仪表显示车速、限速控制、剩余续驶里程计算等使用&#xff0c;因此&#xff0c;在VCU软件开发中&#xff0c;…

有什么免费好用的ai写作软件?2024帮助你快速进行写作的软件

有什么免费好用的ai写作软件&#xff1f;2024帮助你快速进行写作的软件 AI写作软件如今在提升写作效率、生成灵感、以及帮助完成复杂的写作任务方面表现得越来越出色。以下是五款免费且好用的AI写作软件&#xff0c;它们能够帮助你快速进行写作&#xff0c;无论是博客文章、市…

echarts多组堆叠柱状图

一、效果图 二、代码实现 1、创建容器 <el-card class"box-card"><div slot"header" class"clearfix"><span>课堂学习</span></div><div id"class-learning" style"height: 360px">&l…