基本原理
Spring Security都使用了设计模式中的责任链模式,它们都定义了许多过滤器(Filter),每一个请求都会经过层层过滤器的处理。
其中,Spring Security 在 Servlet 的过滤链(filter chain)中注册了一个过滤器 FilterChainProxy,它会把请求代理到 Spring Security 自己维护的多个过滤链,每个过滤链会匹配一些 URL,如图中的 /foo/**,如果匹配则执行对应的过滤器。过滤链是有顺序的,一个请求只会执行第一条匹配的过滤链。
Spring Security 的配置本质上就是新增、删除、修改过滤器
为便于使用,Spring Security默认实现了很多的过滤器,如 UsernamePasswordAuthenticationFilter
来处理用户名密码的认证, SessionManagementFilter
来管理 Session 等等。
下面以 UsernamePasswordAuthenticationFilter
为例来讲讲Spring Security的认证过程。其实也简单,就两步:
-
UsernamePasswordAuthenticationFilter
拦截器匹配/login
的POST
请求,保存认证信息(用户名和密码) - 最终由用户实现
UsernamePasswordAuthenticationProvider
(authenticate
方法) 进行实际认证
代码逻辑
代码比较清晰,主要关注几点:
- 由
UsernamePasswordAuthenticationFilter
定义了过滤器需要匹配的url -
UsernamePasswordAuthenticationFilter
的父类AbstractAuthenticationProcessingFilter
定义doFilter
方法实现整个认证流程,该过程调用attemtAuthentication
进行认证,保存认证结果并根据结果调用successfulAuthentication
或者unsuccessfulAuthentication
。 -
attemtAuthentication
方法最终会由用户实现的UsernamePasswordAuthenticationProvider
(authenticate
方法) 进行实际认证
UsernamePasswordAuthenticationFilter定义过滤器需要匹配的url(/login
的POST
请求)
UsernamePasswordAuthenticationFilter
继承AbstractAuthenticationProcessingFilter
用于处理/login
的POST
请求
AbstractAuthenticationProcessingFilter定义doFilter
方法实现整个认证流程
在AbstractAuthenticationProcessingFilter
的doFilter
方法中会调用attemptAuthentication
方法,该方法进行认证生成认证结果,最终认证结果由session处理。
UsernamePasswordAuthenticationProvider(authenticate
方法) 进行实际认证
UsernamePasswordAuthenticationFilter执行认证
UsernamePasswordAuthenticationFilter
会实现父类中的attemptAuthentication
方法,该方法首先生成UsernamePasswordAuthenticationToken
保存认证信息。然后调用AuthenticationManager
的authenticate
方法认证。
注意: 不同的filter会将认证信息保存到不同类型的结果中, 后续Spring Security会根据认证信息类型寻找合适的
AuthenticationProvider
进行认证,UsernamePasswordAuthenticationFilter
将结果保存到UsernamePasswordAuthenticationToken
中。
AuthenticationManager调用各AuthenticationProvider执行认证
ProviderManager
实现AuthenticationManager
接口, ProviderManager
首先通过AuthenticationProvider
中的support
方法找到合适的AuthenticationProvider
,然后调用authenticate
认证方法
对于UsernamePasswordAuthenticationFilter
,通常我们需要实现自己的UsernamePasswordAuthenticationProvider
(实现AuthenticationProvider
接口)用于用户名和密码验证以及加入一些需要的用户信息如角色、权限等到认证结果中。
示例:
源码
https://gitee.com/awesome-engineer/spring-cloud-family-bucket
网友评论