0
点赞
收藏
分享

微信扫一扫

Spring Security 实战干货:用户是如何进行登录认证的


1. 前言

我们​​上一篇​​​介绍了​​UsernamePasswordAuthenticationFilter​​的工作流程,留下了一个小小的伏笔,作为一个​Servlet Filter​应该存在一个​​doFilter​​​实现方法,而它却没有,其实它的父类​​AbstractAuthenticationProcessingFilter​​​提供了具体的实现。稍后我们会根据这个实现引出今天的主角​​AuthenticationManager​​,来继续介绍用户的认证过程。

2. AbstractAuthenticationProcessingFilter

​AbstractAuthenticationProcessingFilter​​​作为​​UsernamePasswordAuthenticationFilter​​​的父类,实现了认证过滤器的处理逻辑。我们来看看它的核心方法​​doFilter​​的实现:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

// 先通过请求的uri来判断是否需要认证,比如默认的/login
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);

return;
}

if (logger.isDebugEnabled()) {
logger.debug("Request is to process authentication");
}

Authentication authResult;

try {
// 接着就是执行子类钩子方法attemptAuthentication来获取认证结果对象Authentication ,这个对象不能是空 否则直接返回
authResult = attemptAuthentication(request, response);
if (authResult == null) {
// return immediately as subclass has indicated that it hasn't completed
// authentication
return;
}
// 处理session 策略,这里默认没有任何策略
sessionStrategy.onAuthentication(authResult, request, response);
}
catch (InternalAuthenticationServiceException failed) {
logger.error(
"An internal error occurred while trying to authenticate the user.",
failed);
// 如果遇到异常 就会交给认证失败处理器 AuthenticationFailureHandler 来处理
unsuccessfulAuthentication(request, response, failed);

return;
}
catch (AuthenticationException failed) {
// Authentication failed
unsuccessfulAuthentication(request, response, failed);

return;
}

// 认证成功后继续其它过滤器链 并最终交给认证成功处理器 AuthenticationSuccessHandler 处理
if (continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}

successfulAuthentication(request, response, chain, authResult);
}

大部分逻辑这里是清晰的,关键在于​​attemptAuthentication​​​方法,这个我们已经在​​上一文​​​分析了是通过​​AuthenticationManager​​​的​​authenticate​​方法进行认证逻辑的处理,接下来我们将重点分析这个接口来帮助我们了解Spring Seucirty的认证过程。

3. AuthenticationManager

​AuthenticationManager​​​这个接口方法非常奇特,入参和返回值的类型都是​​Authentication​​​。该接口的作用是对用户的未授信凭据进行认证,认证通过则返回授信状态的凭据,否则将抛出认证异常​​AuthenticationException​​。

3.1 AuthenticationManager 的初始化流程

那么​​AbstractAuthenticationProcessingFilter​​​中的 ​​AuthenticationManager​​​ 是在哪里配置的呢?看过​​Spring Security 实战干货系列​​​应该知道​​WebSecurityConfigurerAdapter​​​中的​​void configure(AuthenticationManagerBuilder auth)​​​是配置​​AuthenticationManager​​​ 的地方, 我根据源码总结了一下​​AuthenticationManager​​ 的初始化流程,相信可以帮助你去阅读相关的源码:


Spring Security 实战干货:用户是如何进行登录认证的_java

AuthenticationManager的初始化流程

需要注意的是如果我们使用自定义配置一定不能按照类似下面的错误示范:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(weChatSecurityConfigProperties.getUserDetailsService());
daoAuthenticationProvider.setPasswordEncoder(multiPasswordEncoder());
auth.authenticationProvider(daoAuthenticationProvider);
// 调用 super 将导致不生效 所以下面语句不要写
super.configure(auth);
}

3.2 AuthenticationManager 的认证过程

​AuthenticationManager​​​的实现类​​ProviderManager​​​管理了众多的​​AuthenticationProvider​​​。每一个​​AuthenticationProvider​​​都只支持特定类型的​​Authentication​​​,如果不支持将会跳过。另一个作用就是对适配的​​Authentication​​​进行认证,只要有一个认证成功,那么就认为认证成功,所有的都没有通过才认为是认证失败。认证成功后的​​Authentication​​就变成授信凭据,并触发认证成功的事件。认证失败的就抛出异常触发认证失败的事件。

Spring Security 实战干货:用户是如何进行登录认证的_Authentication_02

ProviderManager认证Token的流程

从这里我们可以看出认证管理器​​AuthenticationManager​​​针对特定的​​Authentication​​提供了特定的认证功能,我们可以借此来实现多种认证并存。

4. 总结

通过本文我们对​Spring Security​认证管理器​​AuthenticationManager​​​的初始化过程和认证过程进行了分析,如果你熟悉了​​AuthenticationManager​​的逻辑可以实现多种认证方式的并存等能力,实现很多有用的逻辑,这对集成​Spring Security​到项目中非常重要。多多关注:​码农小胖哥​ 获取更多的原创干货。


                                                           欢迎 ​点赞


举报

相关推荐

0 条评论