SpringSecurity详细执行流程

本文详细解析了SpringSecurity中TokenAuthenticationFilter、AbstractAuthenticationProcessingFilter、TokenLoginFilter的工作原理,以及AuthenticationManager和AuthenticationProvider在身份验证中的角色,包括如何获取用户信息、密码验证和成功/失败处理过程。
摘要由CSDN通过智能技术生成

SpringSecurity执行详细步骤:

1.TokenAuthenticationFilter:通过解析请求头中的token获取用户信息实现认证的过滤器

(1)判断是否是登录请求,如果是登录请求,则直接跳过当前过滤器

(2)如果不是登录请求则获取authentication(已认证的authentication)

(3)如果获取不到authentication,则认为该用户没有权限

(4)将已认证的authentication放在上下文对象中

(5)从缓存中获取用户权限数据,将用户权限数据封装到UsernamePasswordAuthenticationToken中 特别需要注意:如果在TokenAuthenticationFilter中创建已认证的UsernamePasswordAuthenticationToken, 后续的用户认证操作将不会执行---UsernamePasswordAuthenticationFilter,如果在TokenAuthenticationFilter中创建的是未 认证的UsernamePasswordAuthenticationToken,SpringSecurity还会继续执行AuthenticationManager.authenticate()这个方法,用于用户认证

 2.AbstractAuthenticationProcessingFilter:UsernamePasswordAuthenticationFilter的父类,doFilter是他的具体实现方法

 (1)判断是否需要认证,如果不需要,则继续执行下一个过滤器--调用 requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。 如果需要验证,则会调用 attemptAuthentication(HttpServletRequest, HttpServletResponse) 方法。 有三种结果:

        1、返回一个 Authentication 对象.配置的 SessionAuthenticationStrategy 将被调用,然后调用 successfulAuthentication(HttpServletRequest,HttpServletResponse,FilterChain,Authentication) 方法。

        2、验证时发生 AuthenticationException。unsuccessfulAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationException) 方法将被调用。

        3、返回Null,表示身份验证不完整。假设子类做了一些必要的工作(如重定向)来继续处理验证,方法将立即返回.假设后一个请求将被这种方法接收,其中返回的Authentication对象不为空。

(2)如果需要认证,则UsernamePasswordAuthenticationFilter会实现父类的attemptAuthentication()方法

  (3)将认证成功的 Authentication 对象保存到 HttpSession 中,以便后续的请求可以获取到用户的认证信息, 更新用户的会话状态,例如将会话标记为已认证、设置会话过期时间等。

  (4)如果发生异常调用登录失败的方法

  (5)如果发生异常调用登录失败的方法

(6)continueChainBeforeSuccessfulAuthentication:认证成功后,判断用户是否需要继续向下执行过滤器,continueChainBeforeSuccessfulAuthentication默认值为false,默认认证成功后,不会继续向下执行过滤器,如需继续向下执行,需自定义过滤器并设置continueChainBeforeSuccessfulAuthentication为true

(7)调用登录成功地方法

3.TokenLoginFilter:UsernamePasswordAuthenticationFilter的实现类,主要实现了认证方法:attemptAuthentication

认证成功地方法:successfulAuthentication 认证失败的方法:unsuccessfulAuthentication

(1)设置认证管理器:是定义 Spring Security 的过滤器如何执行Authentication 身份验证的 API .

(2)设置身份验证过滤器需要处理的请求路径和请求方式,默认情况下,Spring Security 对所有的请求都会进行身份验证,但并不是所有请求都需要进行身份验证,因此我们可以使用 setRequiresAuthenticationRequestMatcher 方法来指定哪些请求需要进行身份验证。如果不设置此参数,程序会进入到路径为 “/admin/system/index/login”的登录方法中,如果设置了这个参数,程序不会进入到路径为“/admin/system/index/login”的方法中, 在springSecurity中就进行了登录校验

(3)从request中取出用户登录信息

(4)将用户登录信息,封装到Usern5amePasswordAuthenticationToken中。

(5)调用AuthenticationManager的authenticate方法进行身份认证 

4.从源码可以看出AuthenticationManager接口只包含一个authenticate()方法,它的实现类主要包括以下5个

ProviderManager是AuthenticationManager最重要的一个实现类, ProviderManager委托给AuthenticationProviders列表。 每个AuthenticationProvider都有机会表明身份验证应该是成功的,失败的,或者表明它不能做出决定,并允许下游的AuthenticationProvider来做出决定。 如果配置的AuthenticationProviders中没有一个可以进行身份验证,那么身份验证将会失败,并会出现一个ProviderNotFoundException异常,这是一个特殊的AuthenticationException,表明ProviderManager没有被配置为支持所传入的身份验证类型。从源码中可以看到 ProviderManager委托给AuthenticationProviders列表,即providers为ProviderManager的一个list集合的成员变量。

NoOpAuthenticationManager 是 Spring Security 提供的一个身份验证管理器实现,它的作用是不进行任何身份验证操作。 在某些情况下,我们可能希望跳过身份验证过程,直接将用户认为是已经通过身份验证的。这可能是因为我们信任请求中携带的身份信息,或者我们已经在其他地方对用户进行了身份验证。 NoOpAuthenticationManager 提供了一种简单的方式来实现这一点。它会接受任何传入的 Authentication 对象,并假设该对象已经经过身份验证。它不会对凭证进行验证,也不会与任何用户存储或认证服务进行交互。

4.1 AuthenticationProvider的14个实现类,多个AuthenticationProviders可以被注入到ProviderManager中。

每个AuthenticationProvider执行特定类型的身份验证。 例如,DaoAuthenticationProvider支持基于用户名/密码的身份验证,而JwtAuthenticationProvider支持验证JWT令牌。

5.ProviderManager委托给AuthenticationProvider列表,AuthenticationProvider是一个接口,根据AuthenticationProvider列表(providers)循环调用authenticate方法,进行检测;
6.AbstractUserDetailsAuthenticationProvider:AbstractUserDetailsAuthenticationProvider 是 AuthenticationProvider 接口的一个常见实现。

它提供了一些通用的功能和模板方法,方便我们实现自定义的身份验证逻辑。

6.1 在该方法中首先从缓存中查询,如果没有通过username调用我们实现的接口UserDetailsService,获取数据库中的用户信息;然后进行数据库用户和输入用户数据的passwrod的比较
6.1.1 DaoAuthenticationProvider的retrieveUser() 方法:获取用户信息,一般需要我们自定义DaoAuthenticationProvider下的loadUserByUsername()方法
6.1.1.1:UserDetialsServiceImpl:UserDetailsService的实现类,实现loadUserByUsername()方法

(1)根据用户名去数据库中查询用户信息

(2)根据用户id去查询该用户的按钮权限

 6.2 校验密码是否正确

additionalAuthenticationChecks:DaoAuthenticationProvider的一个方法

presentedPasseord:前端传过来的用户密码

userDetails.getPassword():数据库中查出来的用户密码

如果两者密码不匹配,则抛出异常,如果密码相同,则执行下一步流程

6.2.1:CustomMd5PasswordEncoder:自定义的MD5加密算法
7.创建一个成功的Authentication:AbstractUserDetailsAuthenticationProvider下的authenticate方法
8.此时TokenLoginFilter的attemptAuthentication()方法,返回一个已认证的Authentication

9.此时AbstractAuthenticationProcessingFilter的doFilter()方法:authResult!=null,程序继续向下执行,最终调用认证成功的方法successfulAuthentication()

至此,SpringSecurity源码全部执行完毕。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值