Spring Security认证基本原理

基本原理

Spring Security都使用了设计模式中的责任链模式,它们都定义了许多过滤器(Filter),每一个请求都会经过层层过滤器的处理。



其中,Spring Security 在 Servlet 的过滤链(filter chain)中注册了一个过滤器 FilterChainProxy,它会把请求代理到 Spring Security 自己维护的多个过滤链,每个过滤链会匹配一些 URL,如图中的 /foo/**,如果匹配则执行对应的过滤器。过滤链是有顺序的,一个请求只会执行第一条匹配的过滤链。

Spring Security 的配置本质上就是新增、删除、修改过滤器

为便于使用,Spring Security默认实现了很多的过滤器,如 UsernamePasswordAuthenticationFilter 来处理用户名密码的认证, SessionManagementFilter 来管理 Session 等等。
下面以 UsernamePasswordAuthenticationFilter 为例来讲讲Spring Security的认证过程。其实也简单,就两步:

  1. UsernamePasswordAuthenticationFilter 拦截器匹配/loginPOST请求,保存认证信息(用户名和密码)
  2. 最终由用户实现UsernamePasswordAuthenticationProvider(authenticate方法) 进行实际认证

代码逻辑

代码比较清晰,主要关注几点:

  1. UsernamePasswordAuthenticationFilter定义了过滤器需要匹配的url
  2. UsernamePasswordAuthenticationFilter的父类AbstractAuthenticationProcessingFilter定义doFilter方法实现整个认证流程,该过程调用attemtAuthentication进行认证,保存认证结果并根据结果调用successfulAuthentication或者unsuccessfulAuthentication
  3. attemtAuthentication方法最终会由用户实现的UsernamePasswordAuthenticationProvider(authenticate方法) 进行实际认证

UsernamePasswordAuthenticationFilter定义过滤器需要匹配的url(/loginPOST请求)

UsernamePasswordAuthenticationFilter继承AbstractAuthenticationProcessingFilter用于处理/loginPOST请求

UsernamePasswordAuthenticationFilter

AbstractAuthenticationProcessingFilter定义doFilter方法实现整个认证流程

AbstractAuthenticationProcessingFilterdoFilter方法中会调用attemptAuthentication方法,该方法进行认证生成认证结果,最终认证结果由session处理。

AbstractAuthenticationProcessingFilter

UsernamePasswordAuthenticationProvider(authenticate方法) 进行实际认证

UsernamePasswordAuthenticationFilter执行认证
UsernamePasswordAuthenticationFilter会实现父类中的attemptAuthentication方法,该方法首先生成UsernamePasswordAuthenticationToken保存认证信息。然后调用AuthenticationManagerauthenticate方法认证。

UsernamePasswordAuthenticationFilter

注意: 不同的filter会将认证信息保存到不同类型的结果中, 后续Spring Security会根据认证信息类型寻找合适的AuthenticationProvider进行认证,UsernamePasswordAuthenticationFilter将结果保存到UsernamePasswordAuthenticationToken中。

AuthenticationManager调用各AuthenticationProvider执行认证
ProviderManager实现AuthenticationManager接口, ProviderManager首先通过AuthenticationProvider中的support方法找到合适的AuthenticationProvider,然后调用authenticate认证方法

ProviderManager

对于UsernamePasswordAuthenticationFilter,通常我们需要实现自己的UsernamePasswordAuthenticationProvider(实现AuthenticationProvider接口)用于用户名和密码验证以及加入一些需要的用户信息如角色、权限等到认证结果中。
示例:

UsernamePasswordAuthenticationProvider实现示例

源码

https://gitee.com/awesome-engineer/spring-cloud-family-bucket