Spring Security之源码剖析

1. 认证源码剖析

在这里插入图片描述

1.1 doFilter方法

  1. AbstractAuthenticationProcessingFilter进入doFilter,判断提交方式是不是post请求,如果是,则进行下一步的认证,否则放行则进入下一个过滤器。
    在这里插入图片描述
  2. 调用子类的attemptAuthentication方法获取表单的数据进行验证,返回Authentication。
    Authentication是用来存储用户认证信息的类
    在这里插入图片描述
  3. Session策略处理(如果配置了用户Session最大并发数,就是在此处进行判断并处理
    在这里插入图片描述
  4. 认证成功,调用认证成功的方法successfulAuthentication
    在这里插入图片描述
    认证失败,调用认证失败的方法unsuccessfulAuthentication
    在这里插入图片描述

1.2 attemptAuthentication方法

上述的 第二 过程调用了 UsernamePasswordAuthenticationFilter 的attemptAuthentication() 方法,源码如下:
UsernamePasswordAuthenticationFilter:子类
attemptAuthentication:方法
在这里插入图片描述
完整的attemptAuthentication方法:
在这里插入图片描述
(1)默认情况下,如果请求方式不是Post,会抛出异常。
在这里插入图片描述
(2)获取请求携带的usernane和password
在这里插入图片描述
(3)使用前端传入的usernane、password构造Authentication对象,标记该对象未认证。
在这里插入图片描述
(4)将请求中的一些属性信息设置到Authentication对象中,如:remoteAddress,sessionId
在这里插入图片描述
(5)调用ProviderManager类的authenticate()方法进行身份认证
在这里插入图片描述

1.3 UsernamePasswordAuthenticationToken类

上述的1.2 attemptAuthentication方法(3)过程创建的 UsernamePasswordAuthenticationToken 是Authentication 接口的实现类,该类有两个构造器,一个用于封装前端请求传入的未认证的用户信息,一个用于封装认证成功后的用户信息:

用于封装前端请求传入的未认证的用户信息,前面的 authRequest对象就是调用该杓造器进行构造的
在这里插入图片描述
用封装认证成功后的用户信息
在这里插入图片描述

1.4 Authentication接口

Authentication 接口的实现类用于存储用户认证信息,查看该接口具体定义
在这里插入图片描述

1.5 authenticate方法

上述1.2 attemptAuthentication方法(6)过程中,UsernamePasswordAuthenticationFilter 过滤器的attemptAuthentication() 方法的(5)过程将未认证的 Authentication 对象传入ProviderManager 类的 authenticate() 方法进行身份认证

ProviderManager 是 AuthenticationManager 接口的实现类
在该接口的常用实现类 ProviderManager 内部会维护一个List<AuthenticationProvider>列表,存放多种认证方式,实际上这是委托者模式(Delegate)的应用。每种认证方式对应着一个 AuthenticationProvider,AuthenticationManager 根据认证方式的不同(根据传入的 Authentication 类型判断)委托对应的 AuthenticationProvider 进行用户认证。

完整的authenticate代码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
源码说明:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.6 eraseCredentials方法

上述1.5 authenticate方法认证成功之后的(6)过程,调用 CredentialsContainer 接口定义的eraseCredentials() 方法去除敏感信息。查看UsernamePasswordAuthenticationToken 实现的 eraseCredentials() 方法,该方法实现在其父类中:

在这里插入图片描述
在这里插入图片描述

1.7 认证成功/失败处理

上述过程就是认证流程的最核心部分,接下来重新回到UsernamePasswordAuthenticationFilter 过滤器的 doFilter() 方法,查看认证成功/失败的处理:
在这里插入图片描述
在这里插入图片描述

2. 授权源码剖析

上一个部分通过源码的方式介绍了认证流程,下面介绍权限访问流程,主要是对ExceptionTranslationFilter过滤器和 FilterSecurityInterceptor 过滤器进行介绍。

2.1 ExceptionTranslationFilter 过滤器

该过滤器是用于处理异常的,不需要我们配置,对于前端提交的请求会直接放行,捕获后续抛出的异常并进行处理(例如:权限访问限制)。具体源码如下:
在这里插入图片描述

2.2 FilterSecurityInterceptor 过滤器

FilterSecurityInterceptor 是过滤器链的最后一个过滤器,该过滤器是过滤器链的最后一个过滤器,根据资源权限配置来判断当前请求是否有权限访问对应的资源。如果访问受限会抛出相关异常,最终所抛出的异常会由前一个过滤器ExceptionTranslationFilter 进行捕获和处理。具体源码如下:
在这里插入图片描述
在这里插入图片描述

需要注意,Spring Security 的过滤器链是配置在 SpringMVC 的核心组件DispatcherServlet 运行之前。也就是说,请求通过 Spring Security 的所有过滤器,不意味着能够正常访问资源,该请求还需要通过 SpringMVC 的拦截器链。

2.3 SpringSecurity 请求间共享认证信息

一般认证成功后的用户信息是通过 Session 在多个请求之间共享,那么 Spring Security 中是如何实现将已认证的用户信息对象 Authentication 与 Session 绑定的进行具体分析。
在这里插入图片描述
在前面讲解认证成功的处理方法 successfulAuthentication() 时,有以下代码:
在这里插入图片描述

2.4 SecurityContext 接 口

查 看 SecurityContext 接 口 及 其 实 现 类 SecurityContextImpl , 该 类 其 实 就 是 对 Authentication 的封装
在这里插入图片描述

2.5 SecurityContextHolder类

查 看 SecurityContextHolder 类 , 该 类 其 实 是 对 ThreadLocal 的 封 装 , 存 储 SecurityContext 对象:

SecurityContextHolder
在这里插入图片描述
底层使用了ThreadLocal
在这里插入图片描述
使用ThreadLocal 对Securitycontext进行存储
需要汪意,如果当前线程对应的ThreadLocal<SecurityContext>没有任何对象存储, ! getcontext()会创建并返回一个空的SecurityContext对象,并且该空的SecurityContext 对象会存入ThreadLocal<SecurityContext>
在这里插入图片描述
在这里插入图片描述

2.6 SecurityContextPersistenceFilter 过滤器

前面提到过,在 UsernamePasswordAuthenticationFilter 过滤器认证成功之后,会在认证成功的处理方法中将已认证的用户信息对象 Authentication 封装进SecurityContext并存入 SecurityContextHolder

之后,响应会通过 SecurityContextPersistenceFilter 过滤器,该过滤器的位置在所有过滤器的最前面,请求到来先进它,响应返回最后一个通过它,所以在该过滤器中处理已认证的用户信息对象 Authentication 与 Session 绑定

认证成功的响应通过 SecurityContextPersistenceFilter 过滤器时,会从SecurityContextHolder 中取出封装了已认证用户信息对象 Authentication 的SecurityContext,放进 Session 中。当请求再次到来时,请求首先经过该过滤器,该过滤器会判断当前请求的 Session 是否存有 SecurityContext 对象,如果有则将该对象取出再次放入 SecurityContextHolder 中,之后该请求所在的线程获得认证用户信息,后续的资源访问不需要进行身份认证;当响应再次返回时,该过滤器同样从 SecurityContextHolder 取出SecurityContext 对象,放入 Session 中。具体源码如下:

在这里插入图片描述
(1)请求到来时,检查当前Session中是否存有SecurityContext对象,如果有,从Sess1on中取出该对象;如果没有,创建一个空的SecurityContext 对象
在这里插入图片描述
(2)将上述获得SecuritvContext 对象放入securitvcontextHolder中
在这里插入图片描述
(3)进入下一个过滤器
在这里插入图片描述
(4)响应返回时,从SecurityContextHolder中取出SecurityContext
在这里插入图片描述
(5) 移除SecuritycontextHolder中的Securitycontext对象
在这里插入图片描述
(6)将取出的SecurityContext对象放进session
在这里插入图片描述

内容参考:https://www.bilibili.com/video/BV15a411A7kP
仅用于学习!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Security是一个功能强大的安全框架,它提供了可靠的身份认证和授权机制。在Spring Security源码中,有几个主要的关键点。 首先,在Spring Boot启动过程中,会加载`spring.factories`文件,该文件中包含了对Spring Security的过滤器链的配置信息。这些过滤器链的配置会在DispatcherServlet之前加载。 其次,需要注意的是,Spring Security的过滤器链配置在SpringMVC的核心组件DispatcherServlet运行之前。这意味着请求首先会经过Spring Security的过滤器链,然后需要通过SpringMVC的拦截器链才能正常访问资源。 另外,Spring Security还提供了一种请求间共享认证信息的机制。通过使用`springSecurityFilterChain`方法来声明过滤器链,并通过`webSecurity.build()`方法构建过滤器。 总结起来,Spring Security源码主要包括过滤器链加载流程以及认证流程。过滤器链加载流程在Spring Boot启动时加载`spring.factories`文件,并配置在DispatcherServlet之前。而认证流程则负责处理身份认证和授权的逻辑。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringSecurity源码分析](https://blog.csdn.net/wuzhixuana/article/details/121965713)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Spring Security源码剖析](https://blog.csdn.net/Yearingforthefuture/article/details/117303983)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值