本文内容来自王松老师的《深入浅出Spring Security》,自己在学习的时候为了加深理解顺手抄录的,有时候还会写一些自己的想法
登录流程分析
要搞请求Spring Security认证流程,我们先得认识与之相关的三个基本组件:AuthenticationManager、ProviderManager、AuthenticationProvider,同时还要去了解接入认证器的过滤器AbstractAuthenticationProcessingFilter,这四个类搞清楚了,基本上认证流程也清楚了。
AuthenticationManager
从名称上看AuthenticationManager是一个认证管理器,它定义了Spring Security过滤器要如何执行认证操作。AuthenticationManager在认证成功后会返回一个Authentication对象,这个Authenticaiton会被设置到SecurityContextHolder中。
public interface AuthenticationManager {Authentication authenticate(Authentication authentication) throws AuthenticationException;}
从AuthenticationManager的源码中可以看到AuthenticationManager接受一个Authentication对象进行身份认证,此时传入的Authentication对象只包含简单的用户名和密码等简单的属性,如果认证成功之后返回的Authentication的属性会得到填充,包含用户具备的角色信息。
AuthenticationManager是一个接口,它有诸多的实现类,开发者可以自定义AuthenticationManager的实现类。不过在实际开发中,我们使用的最多的是providerManager。在Spring Security框架中默认也是使用ProviderManager。
AuthenticationProvider
Spring Security支持多种不同的认证方式,不同的认证方式对应不同的身份类型,AuthenticationProvider是针对不同的身份类型执行具体的身份认证。例如常见的DaoAuthenticationProvider用来支持用户名/密码登录认证。其源码如下:
public interface AuthenticationProvider {Authentication authenticate(Authentication authentication) throws AuthenticationException;boolean supports(Class authentication);}
authenticate方法用来执行具体的认证方式
supports方法用来判断当前的AuthenticationProvider是否支持对应的身份认证
ProviderManager
ProviderManager是AuthenticationManager的一个重要实现类,在前面学习的章节中有提到。下面这幅图可以清楚的反应ProviderManager和AuthenticationProvider的关系:
在Spring Security中,由于系统中可能会同时支持多种不同的认证方式,例如:用户名/密码、验证码、手机号码动态验证。而不同的认证方式对应了不同的AuthenticaitonProvider,所以一个完整的认证流程可能由多个AuthenticationProvider来提供。
多个AuthenticationProvider将组成一个列表,这个列表将由ProviderManager来代理。换句话说,在ProviderManager中遍历列表中的每一个AuthenticationProvider去身份认证,最终得到一个认证结果。
我们重点看一下ProviderManager的authenticate方法:
@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {ClassAbstractAuthenticationProcessingFilter作为一个抽象类,如果使用用户名/密码登录,那么它对应的实现类是UsernamePasswordAuthenticationFilter,构造出来Authenticaiton的对象则是UsernamePasswordAuthenticaitonToken。至于AuthenticationManager前面学习过,一般情况下她的实现类是ProviderManager,这里在ProviderManager中认证。认证成功会进入成功的回调,否则进入失败的回调。因此对于上面的流程可以再详细一点:
所以认证的基本流程是这样:
- 当用户提交登录请求时,UsernamePasswordAuthenticationFilter会从当前请求的HttpServletRequest中提取出用户名、密码,然后创建一个UsernamePasswrodToken对象
- UsernamePasswordAuthenticationToken对象作为一个Authenticaiton对象传入ProvoderManager中进行具体的认证
- 如果认证失败,则会进行登录信息存储、Session处理、登录成功事件发布以及登录成功方法回调等操作
- 如果登录失败,则SecurityContextHolder中相关信息将被清除,登录失败回调也会被调用