SpringBoot3+SpringSecurity6基于若依系统整合自定义登录流程

SpringBoot3+SpringSecurity6基于若依系统整合自定义登录流程

问题背景

在做项目时遇到了要对接统一认证的需求,但是由于框架的不兼容性(我们项目是springboot3,jdk17,springsecurity6.1.5)等因素,不得不使用抽离服务的方法,将统一认证服务抽出去形成一个中介系统,统一认证服务使用jdk8的版本,这样可以兼容统一认证服务器,认证流程图大致如下:

在这里插入图片描述

也就是说,我们的任务变成了这样:中介系统会传入一个工号和一个密钥,主系统需要解密密钥并且将根据工号直接登录。一开始我想直接在这个第三方登录方法中就解密密钥,然后复用正常的登录逻辑,正常的登录逻辑是通过工号和密码,框架才会颁发token,密码可以直接从数据库里查出来,所以直接一股脑塞进去:

在这里插入图片描述

但是我们发现框架底层的鉴权流程是:将传入的密码加密,然后查询数据库中存储的密码,而数据库存储的密码本身就是加密后的,相当于匹配这两个字符串是否一致即可(因为这个加密方法是无法逆向解密的)。

这也就是说明我们如果直接从数据库查询密码塞到token里是不行的,因为框架会将你传入的密码再加密一次,就是原来的值了。

在网上看到有说在密码前加入{noop}就可以使得框架不对密码进行加密,但是我尝试后发现没有效果…

没办法,这时候只能自己去实现一个登录流程了。

尝试

在网上查阅了相关文章,找到了SpringSecurity中正常使用账号密码登录走的流程吧:

在这里插入图片描述

根据这个认证过程,我们应该可以大致去效仿一下:

首先我们提供一个实现了AbstractAuthenticationProcessingFilter抽象类的过滤器,用来代替UsernamePasswordAuthenticationFilter逻辑,然后提供一个AuthenticationProvider实现类代替AbstractUserDetailsAuthenticationProvider或DaoAuthenticationProvider,最后再提供一个UserDetailsService实现类。

大致流程是这样。但是别忘了,我们这是springboot3,网上大部分文章都是springboot2的,我们很难找到参考…

因为我们这个项目本身是想整合cas登录的,所以后面很多鉴权逻辑类的起名都跟cas有关。

照猫画虎,根据框架的UsernamePasswordAuthenticationToken我们也自定义了CasAuthenticationToken,大致就是把字段改改,剩下就是完全照搬。

public class CasAuthenticationToken  extends AbstractAuthenticationToken {

    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
    //对应工号
    private final Object principal;
    //对应验证码
    private Object credentials;

    public CasAuthenticationToken(String empId, Object credentials){
        super(null);
        this.principal = empId;
        this.credentials = credentials;
        setAuthenticated(false);
    }

    public CasAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities, Object credentials){
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

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

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


    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
        credentials = null;
    }
}

然后需要写一个Provider,参考SpringSecurity的AbstractUserDetailsAuthenticationProvider,我们也可以照猫画虎一下。注意一下:Provider里面的authenticate方法是鉴权核心代码,比如我们将如何判断密钥合法、根据工号查询用户信息及是否有这个用户等,这里的逻辑需要你们去个性化实现。

@Component
public class CasAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    public CasAuthenticationProvider(UserDetailsService userDetailService) {
        this.userDetailsService = userDetailService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        CasAuthenticationToken token = (CasAuthenticationToken) authentication;
        String empId = (String)token.getPrincipal();
        //首先,验证验证码是否正确
        String code = (String)token.getCredentials();
        //这里应该写一下如何解密的逻辑
       -----------------
        //然后,查询对应用户
        UserDetails user = userDetailsService.loadUserByUsername(empId);
        if (Objects.isNull(user)) {
            throw new InternalAuthenticationServiceException("根据工号:" + empId + ",无法获取对应的用户信息!");
        }
        CasAuthenticationToken authenticationResult = new CasAuthenticationToken(user, user.getAuthorities(), token.getCredentials());
        authenticationResult.setDetails(token.getDetails());
        return authenticationResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return CasAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

值得注意的是,返回新的CasAuthenticationToken中第一个参数user信息要是一个对象,这样便于后面解析成LoginUser对象。

看网上大部分文章还需要配置专门的第三方过滤器、专门的登录成功类和登录失败类,一开始我也根据这个创了好多,最后打断点才发现根本都没进到这些代码里来。

大部分文章还要求在SpringSecurity配置类配置下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/error","/login/**","/login/goLogin","/login/doLogin","/login/code","/login/authorization_code").anonymous()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login/goLogin")
            .loginProcessingUrl("/login/doLogin")
            .failureUrl("/login/error")
            .permitAll()
            .successHandler(new QriverAuthenticationSuccessHandler("/index/toIndex"));

	//这里我们省略了一些配置 ……

	//应用前面定义的配置
    http.apply(thirdAuthenticationSecurityConfig);
}

但是我的项目是springboot3+springsecurity6,不能这么写,已经从configure方法变成了filterChain方法,像一个链子一样调用不同的过滤器来实现统一过滤。

看到过滤器链里有这个UsernamePasswordAuthenticationFilter,我也不假思索的觉得应该弄一个CasAuthenticationFilter并且插入进去,但是不知为什么弄完后,填入过滤链项目就无法启动了,报错:The Filter class org.**.ThirdAuthenticationFilter does not have a registered order…网上搜了一下说加@Order的仍然还是一样报错。哎,那还是注掉吧

在这里插入图片描述

嗯,那就算了?要不就先这样试试能不能成功

满怀期待的启动项目测试,结果报错:No AuthenticationProvider found for org.***.CasAuthenticationToken

根据资料显示,是由于我定义了一个新的AuthenticationToken,在

authenticationManager.authenticate(authenticationToken);

时候发现authenticationManager的parent属性是null,他不知道如何对我们这个自定义的token进行鉴权。哎不对啊,我前面明明写了个Provider为什么还不行!

看一些可能是SpringBoot2的文章说要弄filter,但是我弄了但是根本不走代码,放到SecurityConfig里又报错无法启动项目。应该是不同版本写法已经不一样了。

其实首要问题就是AuthenticationManager的parent属性是null,应该从这里入手。但是我走错方向了,不停的在SecurityConfig配置上、过滤器上改…

后面我想到了这个AuthenticationManager,偶然在SecurityConfig看到了:

在这里插入图片描述

还记得账号密码怎么登录的吗,他用的DaoAuthenticationProvider!这里他给ProviderManager注入了!

点进去看了一下,他可以注入多个Provider!那我们直接把CasAuthenticationProvider注入!
在这里插入图片描述

那我们就可以照猫画虎!注入!

在这里插入图片描述

最后测试一下,能成功返回token了!

参考文章:

一文理清SpringSecurity中基于用于名密码的登录认证流程-腾讯云开发者社区-腾讯云 (tencent.com)

SpringSecurity自定义多Provider时提示No AuthenticationProvider found for问题的解决方案与原理(二)-CSDN博客

SpringSecurity系列 之 集成第三方登录(包括默认的用户名密码、短信验证码和github三种登录方式)_springsecurity第三方登录-CSDN博客

Spring Security authenticationManager()返回null,必须定义authenticationManagerBean的原因分析-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mount Image Pro,在取证安全的环境中挂载和访问镜像文件内容

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据恢复、数据备份解决方案与服务&#xff0c;并针对企业面临的数据安全风险&#xff0c;提供专业的相关数据安全培训。 天津鸿萌科贸发展有限公司是 GetData 公司数据恢复与取证工…

PHP合成图片,生成海报图,poster-editor使用说明

之前写过一篇使用Grafika插件生成海报图的文章&#xff0c;但是当我再次使用时&#xff0c;却发生了错误&#xff0c;回看Grafika文档&#xff0c;发现很久没更新了&#xff0c;不兼容新版的GD&#xff0c;所以改用了intervention/image插件来生成海报图。 但是后来需要对海报…

React 前端框架全面教程:从入门到进阶

React 前端框架全面教程&#xff1a;从入门到进阶 引言 在现代前端开发中&#xff0c;React 作为一款流行的 JavaScript 库&#xff0c;以其组件化、声明式的特性和强大的生态系统&#xff0c;成为了开发者的首选。无论是构建单页应用&#xff08;SPA&#xff09;还是复杂的用…

基于Python的自然语言处理系列(42):Token Classification(标注分类)

在本篇文章中&#xff0c;我们将探讨如何进行 Token Classification&#xff08;标注分类&#xff09;&#xff0c;这是一类为句子中的每个 token&#xff08;词或子词&#xff09;分配标签的任务。该任务可以解决很多问题&#xff0c;例如命名实体识别&#xff08;NER&#xf…

用Pyhon写一款简单的益智类小游戏——2048

文字版——代码及讲解 代码—— import random# 初始化游戏棋盘 def init_board():return [[0] * 4 for _ in range(4)]# 在棋盘上随机生成一个2或4 def add_new_tile(board):empty_cells [(i, j) for i in range(4) for j in range(4) if board[i][j] 0]if empty_cells:i,…

『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC

『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC 文章目录 一. 『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC1. 介绍 二. 参考文献 一. 『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC 如何在 Ubuntu 22.04 上安装和配置 VNC 1. 介绍 虚拟网络计算…

【Java】方法的使用 —— 语法要求、方法的重载和签名、方法递归

目录 1. 方法基础知识 1.1 方法的概念 1.2 语法格式 * 注意事项【与C不同】 1.3 return —— 返回值的严格检查【比C语言严格】 2. 形参与实参的关系 3. 方法重载 3.1 什么是方法重载&#xff1f;为什么要方法重载&#xff1f; 3.2 方法重载的规则 4. 方法签名 5. 递…

HT7178 带输出关断的20V,14A全集成同步升压转换器

1、特点 输入电压范围VpIN:2.7V-20V 输出电压范围VouT:4.5V-20V 可编程峰值电流:14A 高转换效率: 95%(VPIN7.2V, VoUT 16V, IouT3A) 94%(VPIN12V,VoUT18V,IoUT4A) 90%(VPIN3.3, VoUT-9V,IOUT3A) 轻载条件下两种调制方式:脉频调制(PFM)和 强制脉宽调试(PWM) 集成输出关断的栅极…

【史上最全SD教程】Stable Diffusion系统教学!Ai绘画零基础入门到精通商业实战 人工智能绘图画图商业变现

一、为什么要学Stable Diffusion&#xff0c;它究竟有多强大&#xff1f; 1.Stable Diffusion能干嘛 Stable Diffusion&#xff08;SD&#xff09;作为一种先进的AI图像生成技术&#xff0c;其功能和应用场景非常广泛。以下是SD的一些主要功能和应用领域&#xff1a; \1. 图…

《链表篇》---两数相加(中等)

题目传送门 方法一&#xff1a;迭代 文字描述看代母注释 class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {//定义头结点和当前节点ListNode head null,cur null;//carry记录进位情况。int carry 0; while(l1 ! null || l2 ! null){//判断节点是…

QT找不到ffmpeg链接库解决方法

error: undefined reference to avformat_network_init() 一个神奇的报错&#xff0c;查了很久&#xff0c;检查步骤&#xff1a; 1、检查了 pro工程文件 2、链接库的真实性和正确性 在main.cpp中调用没有报错&#xff0c;在其它cpp文件中调用就报错。 破案了&#xff0c;…

详细了解C++11(1)

大家好呀&#xff0c;我是残念&#xff0c;希望在你看完之后&#xff0c;能对你有所帮助&#xff0c;有什么不足请指正&#xff01;共同学习交流哦 本文由&#xff1a;残念ing原创CSDN首发&#xff0c;如需要转载请通知 个人主页&#xff1a;残念ing-CSDN博客&#xff0c;欢迎各…

04.DDD与CQRS

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 定义职责分离DDD与CQRS的关系领域模型和查询模型特点命令场景的领域模型查询场景的查询模型 架构方案领域事件方案1&#xff1a…

【运动的&高尔夫球】高尔夫球检测系统源码&数据集全套:改进yolo11-CA-HSFPN

改进yolo11-HWD等200全套创新点大全&#xff1a;高尔夫球检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.30 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统图片或者视频可…

【python】flash-attn安装

这个命令&#xff1a; 确保使用正确的 CUDA 12.6 工具链 设置必要的 CUDA 环境变量 包含了常见的 GPU 架构支持 利用你的128核心进行并行编译 # 清理之前的安装 proxychains4 pip uninstall -y flash-attn# 获取 CUDA 路径 CUDA_PATH$(dirname $(dirname $(which nvcc)))# 使用…

得计算题者得天下!软考系统集成计算题详解!

软考中级系统集成项目管理工程师考试一共有《综合知识》和《案例分析》两门科目&#xff0c;而在这两科中都会涉及到计算题&#xff0c;特别是案例分析中&#xff0c;计算题每次考试都会占到一道大题&#xff0c;共25分&#xff0c;占到了科目总分的1/4&#xff0c;所以对于系统…

第2章 Android App开发基础

第 2 章 Android App开发基础 bilibili学习地址 github代码地址 本章介绍基于Android系统的App开发常识&#xff0c;包括以下几个方面&#xff1a;App开发与其他软件开发有什么不一 样&#xff0c;App工程是怎样的组织结构又是怎样配置的&#xff0c;App开发的前后端分离设计…

腾讯云视频文件上传云存储时自动将mp4格式转码成m3u8

针对问题&#xff1a; 弱网环境下或手机网络播放mp4格式视频卡顿。 存储环境&#xff1a;腾讯云对象存储。 处理流程&#xff1a; 1&#xff1a;登录腾讯云控制台&#xff0c;进入对象存储服务&#xff0c;找到对应的存储桶&#xff0c;点击进入。 在任务与工作流选项卡中找…

如何下载安装TestLink?

一、下载TestLink、XAMPP TestLink 下载 |SourceForge.net 备用&#xff1a;GitHub - TestLinkOpenSourceTRMS/testlink-code&#xff1a; TestLink开源测试和需求管理系统 下载XAMPP&#xff1a; Download XAMPP 注意&#xff1a;TestLink与PHP版本有关系&#xff0c;所以XA…

【AI学习】扩散模型的一点思考:生成过程为什么要增加噪声项

前面学习了扩散模型&#xff0c;并做了总结PPT。 其中有一个疑问&#xff1a;在生成过程中&#xff0c;就是下图的算法2中的第四步&#xff0c;为什么要在预测了噪声项后&#xff0c;Xt减去预测的噪声后&#xff0c;还有再叠加一个噪声项&#xff1f;就是增加的部分。 李宏毅…