首页 > 编程语言 >SpringSecurity-认证流程源码级详解

SpringSecurity-认证流程源码级详解

时间:2024-01-18 12:45:04浏览次数:29  
标签:getAuthentication Authentication 认证 authentication 源码 线程 SpringSecurity public 

自定义用户认证逻辑

处理用户信息获取逻辑:UserDetailsService

处理用户校验逻辑:UserDetails

处理密码加密解密:PasswordEncoder

认证处理流程

IMG_256

以表单认证为例:从发起认证请求到认证过滤器,接着认证成功后,响应从认证过滤器返回的整个过程。SpringSecurity做了什么,设计到了哪些类?他们之间如何调用?
SpringSecurity认证流程中涉及到的主要的类和接口如下:

IMG_256

  1. debug启动,浏览器登录:

IMG_256

2. 进入UsernamePasswordAuthenticationFilter:

IMG_256

IMG_256

IMG_256

3.AuthenticationManager

AuthenticationManager自身并不包含验证逻辑,用来管理AuthenticationProvider;

AuthenticationManager有很多实现类,主要是ProviderManager:

IMG_256

IMG_256

ProviderManager在public Authentication authenticate(Authentication authentication)会进行for循环,获取所有AuthenticationProvider,所有校验逻辑是在AuthenticationProvider里面的,为什么这里是一个集合:是因为不同的登录方式其认证逻辑是不一样的,我们现在是用户名密码登录,是需要去校验密码。如果是微信登录,则又是不一样的。AuthenticationManager作用就是把所有AuthenticationProvider搜集起来,认证时候,挨个去问,你当前的provider支不支持我现在的的登录方式(其实就是做循环,然后调用supports方法)。

IMG_256

IMG_2564.AuthenticationProvider

进入DaoAuthenticationProvider,DaoAuthenticationProvider会调用其父类的AbstractUserDetailsAuthenticationProvider的authenticate方法

IMG_256

IMG_256

附加检查:在DaoAuthenticationProvider--->检查密码是否匹配

IMG_256

然后进行后检查:后检查主要检查4个boolean中最后一个:

IMG_256

如果上面检验全部没问题的话,就认为认证是合法的,然后我们再创建一个已经授权的Authentication

IMG_256

IMG_256

IMG_2565.UserDetailsService

自定义用户认证,实现UserDetailsService接口

6.UserDetails

User是UserDetails实现类

7.登录成功之后走到我们自定义的成功处理器

进入AbstractAuthenticationProcessingFilter

IMG_256

进入自定义成功处理器:

IMG_256

认证结果在多个请求之间共享

多个请求共享肯定是放到session里,那么SpringSecurity是什么时候放到了session里面?什么时候又从session里面读取出来的?

IMG_256

AbstractAuthenticationProcessingFilter里面successfulAuthentication有一个:

SecurityContextHolder.getContext().setAuthentication(authResult);

IMG_256

其实是把认证成功的Authentication放到: SecurityContext里面,然后SecurityContext放到SecurityContextHolder里面。

IMG_256

SecurityContext其实很简单,他就是一个接口,其唯一的实现类是:

IMG_256

package org.springframework.security.core.context;

import org.springframework.security.core.Authentication;

public class SecurityContextImpl implements SecurityContext {
    private static final long serialVersionUID = 420L;
    private Authentication authentication;

    public SecurityContextImpl() {
    }

    public boolean equals(Object obj) {
        if (obj instanceof SecurityContextImpl) {
            SecurityContextImpl test = (SecurityContextImpl)obj;
            if (this.getAuthentication() == null && test.getAuthentication() == null) {
                return true;
            }

            if (this.getAuthentication() != null && test.getAuthentication() != null && this.getAuthentication().equals(test.getAuthentication())) {
                return true;
            }
        }

        return false;
    }

    public Authentication getAuthentication() {
        return this.authentication;
    }

    public int hashCode() {
        return this.authentication == null ? -1 : this.authentication.hashCode();
    }

    public void setAuthentication(Authentication authentication) {
        this.authentication = authentication;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(super.toString());
        if (this.authentication == null) {
            sb.append(": Null authentication");
        } else {
            sb.append(": Authentication: ").append(this.authentication);
        }

        return sb.toString();
    }
}

SecurityContext说明:是对Authentication的包装,并且重写其hashCode和equals,保证其唯一性。

SecurityContextHolder:

  实际上是ThreaadLocal封装,ThreadLocal是跟线程绑定的一个Map,在这个线程里面存放的东西可以在另一个线程读取出来,认证结果存入ThreaadLocalMap,可以让不同方法直接使用,避免重复认证,参数传递的麻烦。

IMG_256

最后:SecurityContextHolder会交给SecurityContextPersistenceFilter过滤器:他的位置在过滤器链的最前端:

IMG_256

SecurityContextPersistenceFilter过滤器作用:

  1. 当请求进来的时候:检查session里面是否有SecurityContext,如果有将其拿出来,然后放到线程里面,如果没有就过去了;响应时候:从线程里面(因为其在过滤器链上最前端,请求先经过此过滤器,然后最后会从这个过滤器出去)
  2. 当整个请求响应回来以后:最后一个过他的时候,他检查线程,如果线程里面有:SecurityContext,就拿出来放到session里面去。

这样不同的请求可以从线程里面拿到认证信息。拿到以后放到线程里面,因为请求和响应是在一个线程中。

获取认证用户信息

@GetMapping("/me")
public Object getCurrentUser(){
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    Object u = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    return authentication;
}

或参数中直接写Authentication authentication

@GetMapping("/me2")
public Object getCurrentUser(Authentication authentication){//框架会注入
    //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    //Object u = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    Object u = authentication.getPrincipal();
    return authentication;
}

只需要UserDetails

@GetMapping("/me3")
public Object getCurrentUser(@AuthenticationPrincipal UserDetails userDetails){//框架会注入
    String username = userDetails.getUsername();
    Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
    boolean accountNonExpired = userDetails.isAccountNonExpired();
    return userDetails;
}

 

标签:getAuthentication,Authentication,认证,authentication,源码,线程,SpringSecurity,public,
From: https://www.cnblogs.com/wangzhilei-src/p/17972253

相关文章

  • 【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(下)
    承接上文在阅读了上篇文章《【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(上)》之后,相信您对HashMap的基本原理和基础结构已经有了初步的认识。接下来,我们将进一步深入探索HashMap的源码,揭示其深层次的技术细节。通过这次解析,您将更深入地理解HashMap的......
  • Android RECYCLEVIEWscrollbarDefaultDelayBeforeFade 源码
    AndroidRecyclerViewscrollbarDefaultDelayBeforeFade源码实现简介在Android开发中,RecyclerView是一个常用的控件,用于展示大数据集合的列表或网格。RecyclerView提供了一些自定义的属性和方法,方便开发者根据需求进行定制。其中一个常用的属性是scrollbarDefaultDelayBefo......
  • Java异步编程详解
    在现代应用程序开发中,异步编程变得越来越重要,特别是在处理I/O密集型任务时。Java提供了一套强大的异步编程工具,使得开发者能够更有效地处理并发任务。本篇博文将深入探讨Java中异步编程的方方面面,通过具体例子详细说明异步编程的实践。异步编程的背景在传统的同步编程模型中,任务......
  • LinkedHashMao & LinkedHashSet源码阅读
    目录简介模型代码分析成员变量方法补充-LinkedHashSet总结参考链接本人的源码阅读主要聚焦于类的使用场景,一般只在java层面进行分析,没有深入到一些native方法的实现。并且由于知识储备不完整,很可能出现疏漏甚至是谬误,欢迎指出共同学习本文基于corretto-17.0.9源码,参考本文时......
  • RocketMQ 中冷热分离的随机索引模块详解
    作者:苏昌盛消息系统中随机索引的特点RocketMQ广泛使用于各类业务场景中,在实际生产场景中,用户通常会选择消息ID或者特定的业务Key(例如学号,订单号)来查询和定位特定的一批消息,进而定位分布式系统中的复杂问题。传统方案下,消息索引的存储是基于数据库系统或者基于本地文件系统实现......
  • 掌上医院预约挂号源码,uni-app+.net公众号、支付宝小程序预约挂号平台
    线上预约挂号系统构建了医院和患者的连接,通过改善患者院内的就医服务流程,以公众号、支付宝小程序为服务入口,为居民提供导诊、预约、支付、报告查询等线上线下一体化的就医服务,缩短患者就诊环节,提高医疗机构服务效率。●与医院HIS系统深度融合,实现诊疗业务及数据线上线下的双向传......
  • RocketMQ 中冷热分离的随机索引模块详解
    作者:苏昌盛消息系统中随机索引的特点RocketMQ广泛使用于各类业务场景中,在实际生产场景中,用户通常会选择消息ID或者特定的业务Key(例如学号,订单号)来查询和定位特定的一批消息,进而定位分布式系统中的复杂问题。传统方案下,消息索引的存储是基于数据库系统或者基于本地文件系统实......
  • ETLCloud详解,如何实现最佳实践及问题排查
    ETLCloud介绍ETLCloud是新一代全域数据集成平台,领先于市场同类产品的数据集成平台(DataOps),只需单击几下即可完成数据清洗转换、传输入仓等操作,具备高效、智能、一站式的全域数据集成优势,如:毫秒级实时数据同步支持异构数据源实时数据监听读取,实时数据通过经过清选、转换后可以实时......
  • Markdown语法详解
    Markdown学习标题:#空格标题名二级标题字体HelloWorld!两边加一个*变成斜体HelloWordl!两边加两个*变成粗体HelloWordl!两边加~~HelloWordl!两边***斜体粗体引用我是一个很牛逼的程序员>空格分割线三个-或者三个*图片!jietu](C:\Users\王牛逼\Deskto......
  • SpringSecurity系列,第四章:源码分析
    源码分析SpringSecurity的核心功能即为:认证(Authentication)、授权(Authorization)一、概览1、在SpringSecurity中,用户的认证信息主要由Authentication的实现类来保存,Authentication接口定义如下:【保存用户认证信息】publicinterfaceAuthenticationextendsPrin......