Spring Security认证流程源码
Spring Security框架大体实现:首先在初始化Spring Security时,会创建一个类型为FilterChainProxy,名为 SpringSecurityFilterChain 的Servlet过滤器,这个过滤器只是一个代理,工作的是类型为SecurityFilterChain过滤器链,负责认证的过滤器会调用认证接口AuthenticationManager;负责授权的过滤器会调用授权接口AccessDecisionManager。

先看一个流程图:

UsernamePasswordAuthenticationFilter

进入UsernamePasswordAuthenticationFilter的方法中,第二个红色方框中的username和password是前端传递的用户名和密码。然后包装为UsernamePasswordAuthenticationToken,这个类实现Authentication接口!包装完成之后调用getAuthenticationManager().authenticate(authRequest)。AuthenticationManager有很多实现类,其中一个就是ProvideManager。将各种认证方式集成到List<AuthenticationProvider> 列表 ,每种认证方式都会实现 AuthenticationProvider接口,其中authenticate()方法定义了认证的实现过程,supports()方法定义支持那种认证类型,认证成功后会返回AuthenticationToken
public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> var1); }
ProvideManager
选择provider

ProvideManager负责管理AuthenticationProvider,可以看到图中有很多的providers,可以有SocialAuthenticationProvider(第三方接入的时候专用),AbstractUserDetailsAuthenticationProvider(配置的时候用到的)等等。其实真正执行的只有一个provider,那么究竟会选择哪一个provider,看到有一个supports方法。也就是根据上一步中的authentication的类型来做判断。
调用provider的authenticate方法
获取用户信息

关键方法就是调用我们自己实现的UserDetailsService类的方法先把用户获取到
检查获取到的用户信息

验证密码是否正确

验证密码是否过期

创建UsernamePasswordAuthenticationToken表示认证成功
![]()
SecurityContextPersistenceFilter
把用户信息认证完了后,其他请求是如何共享这一次登录验证的呢?这个就是靠SecurityContext上下文来完成这项工作的。用户认证完成之后会把UsernamePasswordAuthenticationToken存入到Context中,而Context会存储到session当中去,这样,下一次请求过来的时候,就不用让用户在登录了。那么是谁把认证信息放到Context里面去的呢?答案就是SecurityContextPersistenceFilter,这个Filter处于所有Filter的最前端位置:


授权过程
FilterSecurityInterceptor会调用AccessDecisionManager进行授权决策,若决策通过,则允许访问资源,否则将禁止访问,AccessDecisionManager采用投票的方式来确定是否能够访问受保护资源。
public interface AccessDecisionManager { //decide接口就是用来鉴定当前用户是否有访问对应受保护资源的权限。 void decide(Authentication authentication , Object object, ...) ; }
权限信息保存在SecurityMetadataSource的子类中
antMatchers("/xx/").hasAuthority("X") antMatchers("/yy/").hasAuthority("Y")
浙公网安备 33010602011771号