共计 3259 个字符,预计需要花费 9 分钟才能阅读完成。
1. 前言
咱们上一篇介绍了 UsernamePasswordAuthenticationFilter
的工作流程,留下了一个小小的伏笔,作为一个 Servlet Filter 应该存在一个 doFilter
实现办法,而它却没有,其实它的父类 AbstractAuthenticationProcessingFilter
提供了具体的实现。稍后咱们会依据这个实现引出明天的配角AuthenticationManager
,来持续介绍用户的认证过程。
2. AbstractAuthenticationProcessingFilter
咱们来看看 AbstractAuthenticationProcessingFilter
的外围办法 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
的初始化流程,置信能够帮忙你去浏览相干的源码:
须要留神的是如果咱们应用自定义配置肯定不能依照相似上面的谬误示范:
@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
就变成授信凭据,并触发认证胜利的事件。认证失败的就抛出异样触发认证失败的事件。
从这里咱们能够看出认证管理器 AuthenticationManager
针对特定的 Authentication
提供了特定的认证性能,咱们能够借此来实现多种认证并存。
4. 总结
通过本文咱们对 Spring Security 认证管理器 AuthenticationManager
的初始化过程和认证过程进行了剖析,如果你相熟了 AuthenticationManager
的逻辑能够实现多种认证形式的并存等能力,实现很多有用的逻辑,这对集成 Spring Security 到我的项目中十分重要。多多关注:码农小胖哥 获取更多的原创干货。
关注公众号:Felordcn 获取更多资讯
集体博客:https://felord.cn