爆破专栏丨千锋Spring Security系列教程之Spring Security认证授权流程

本文详细分析了Spring Security的认证授权流程,包括SecurityContextPersistenceFilter、UsernamePasswordAuthenticationFilter、AuthenticationManager与ProviderManager的工作原理。通过源码解析,阐述了从用户登录到Authentication对象创建和权限检查的全过程,帮助读者深入理解Spring Security的内部机制。
摘要由CSDN通过智能技术生成

前言

在上一章节中,一一哥 带大家认识了Spring Security内部关于认证授权的几个核心API,以及这几个核心API之间的引用关系,掌握了这些之后,我们就能进一步研究分析认证授权的内部实现原理了。这样才真正的达到了 "知其所以然"

本篇文章中,壹哥 带各位小伙伴进一步分析认证授权的源码实现,请各位再坚持一下吧......

一. Spring Security认证授权流程图概述

在上一章节中,壹哥就给各位贴出过Spring Security的认证授权流程图,该图展示了认证授权时经历的核心API,并且展示了认证授权流程。接下来我们结合源码,一点点分析认证和授权的实现过程。
 

  大家可以加老师vx领取最新资料哦

二. 简要剖析认证授权实现流程的代码逻辑

Spring Security的认证授权流程其实是非常复杂的,在我们对源码还不够了解的情况下,壹哥先给各位简要概括一下这个认证和授权流程,大致如下:

  1. 用户登录前,默认生成的Authentication对象处于未认证状态,登录时会交由Authentication Manager负责进行认证。

  2. AuthenticationManager会将Authentication中的用户名/密码与UserDetails中的用户名/密码对比,完成认证工作,认证成功后会生成一个已认证状态的Authentication对象;

  3. 最后把认证通过的Authentication对象写入到SecurityContext中,在用户有后续请求时,可从Authentication中检查权限。

我们可以借鉴一下Spring Security官方文档中提供的一个最简化的认证授权流程代码,来认识一下认证授权的实现过程,该代码省略了UserDetails操作,只做了简单认证,可以对认证授权有个大概了解。

 

public class AuthenticationExample {
    
 private static AuthenticationManager am = new SampleAuthenticationManager();
 
 public static void main(String[] args) throws Exception {
  BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 
  while (true) {
            //模拟输入用户名密码
   System.out.println("Please enter your username:");
   String name = in.readLine();
            
   System.out.println("Please enter your password:");
   String password = in.readLine();
            
   try {
    //根据用户名/密码,生成未认证Authentication
    Authentication request = new UsernamePasswordAuthenticationToken(name, password);
                //交给AuthenticationManager 认证
    Authentication result = am.authenticate(request);
    //将已认证的Authentication放入SecurityContext
    SecurityContextHolder.getContext().setAuthentication(result);
    break;
   } catch (AuthenticationException e) {
    System.out.println("Authentication failed: " + e.getMessage());
   }
  }
        
  System.out.println("Successfully authenticated. Security context contains: "
    + SecurityContextHolder.getContext().getAuthentication());
 }
}

//认证类
class SampleAuthenticationManager implements AuthenticationManager {
    //配置一个简单的用户权限集合
 static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
 
    static {
  AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
 }
 
 public Authentication authenticate(Authentication auth) throws AuthenticationException {
        //如果用户名和密码一致,则登录成功,这里只做了简单认证
  if (auth.getName().equals(auth.getCredentials())) {
   //认证成功,生成已认证Authentication,比未认证多了权限
   return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
  }
        
  throw new BadCredentialsException("Bad Credentials");
 }
}

以上代码只是简单的模拟了认证的过程,那么真正的认证授权操作,是不是也这样呢?接下来请跟着 一一哥,咱们结合源码进行详细的剖析。

三. Spring Security认证流程源码详解

1. Spring Security过滤器链执行顺序

在 Spring Security 中,与认证、授权相关的校验其实都是利用一系列的过滤器来完成的,这些过滤器共同组成了一个过滤器链,如下图所示:

图片

你可能会问,我们怎么知道这些过滤器在执行?其实我们只要开启Spring Security的debug调试模式,开发时就可以在控制台看到这些过滤器的执行顺序,如下:

图片

图片

所以在上图中可以看到,Spring Security中默认执行的过滤器顺序如下:

  • WebAsyncManagerIntegrationFilter

  • SecurityContextPersistenceFilter

  • HeaderWriterFilter

  • CsrfFilter

  • LogoutFilter

  • UsernamePasswordAuthenticationFilter

  • DefaultLoginPageGeneratingFilter

  • DefaultLogoutPageGeneratingFilter

  • RequestCacheAwareFilter

  • SecurityContextHolderAwareRequestFilter

  • AnonymousAuthenticationFilter:如果之前的认证机制都没有更新 Security Context Holder 拥有的 Authentication,那么一个 Anonymous Authen  tication Token 将会设给 Security Context Holder。

  • SessionManagementFilter

  • ExceptionTranslationFilter:用于处理在 Filter Chain 范围内抛出的 Access Denied Exception 和 Authentication Exception,并把它们转换为对应的 Http 错误码返回或者跳转到对应的页面。

  • FilterSecurityInterceptor:负责保护 Web URI,并且在访问被拒绝时抛出异常。

2. SecurityContextPersistenceFilter

在上面的过滤器链中,我们可以看到 Security Context PersistenceFilter这个过滤器。Security Context Persistence Filter是Security中的一个拦截器,它的执行时机非常早,当请求来临时它会从Security Context Repository中把SecurityContext对象取出来,然后放入Security Context Holder的Thread Local中。在所有拦截器都处理完成后,再把Security Context存入Security Context Repository,并清除Security Context Holder 内的 Security Context 引用。

3. AbstractAuthenticationProcessingFilter

在上面图中所展示的一系列的过滤器中,和认证授权直接相关的过滤器是 Abstract Authentication Processing Filter 和 Username Password Authentication Filter。但是你可能又会问,怎么没看到 Abstract Authentication Processing Filter 这个过滤器呢?这是因为它是一个抽象的父类,其内部定义了认证处理的过程,Username Password Authentication Filter 就继承自 Abstract Authentication Processing Filter。如下图所示:

图片

从上图中我们可以看出,Abstra

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值