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; if (!requiresAuthentication(request, response)) { chain.doFilter(request, response); return; } if (logger.isDebugEnabled()) { logger.debug("Request is to process authentication"); } try { Authentication authResult = attemptAuthentication(request, response); if (authResult == null) { return; } sessionStrategy.onAuthentication(authResult, request, response); } catch (InternalAuthenticationServiceException failed) { logger.error("An internal error occurred while trying to authenticate the user.", failed); unsuccessfulAuthentication(request, response, failed); return; } catch (AuthenticationException failed) { unsuccessfulAuthentication(request, response, failed); return; } if (continueChainBeforeSuccessfulAuthentication) { chain.doFilter(request, response); } successfulAuthentication(request, response, chain, authResult); }
doFilter 方法的主要逻辑是判断请求是否需要认证,并调用子类的 attemptAuthentication 方法获取认证结果。如果认证成功,则继续执行后续过滤器链;否则,触发认证失败处理器。
3. AuthenticationManager 详解
AuthenticationManager 接口用于对未授信凭据进行认证。该接口的输入和输出类型都是 Authentication。认证通过则返回授信状态的凭据,否则抛出 AuthenticationException。
3.1 AuthenticationManager 初始化流程
AuthenticationManager 在 WebSecurityConfigurerAdapter 的 configure 方法中进行配置。以下是初始化流程的总结:
AuthenticationManager 的初始化流程
需要注意的是,自定义配置时应避免类似以下错误示范:
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { DaoAuthenticationProvider daoAuthenticatiOnProvider= new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(weChatSecurityConfigProperties.getUserDetailsService()); daoAuthenticationProvider.setPasswordEncoder(multiPasswordEncoder()); auth.authenticationProvider(daoAuthenticationProvider); // 不要调用 super.configure(auth); }
3.2 AuthenticationManager 认证过程
AuthenticationManager 的实现类 ProviderManager 管理多个 AuthenticationProvider。每个 AuthenticationProvider 只支持特定类型的 Authentication,如果不支持则跳过。只要有一个认证成功,就认为整体认证成功,所有都失败则认为认证失败。
ProviderManager 认证 Token 的流程
从这里可以看出,AuthenticationManager 针对不同类型的 Authentication 提供了灵活的认证功能,可以实现多种认证方式并存。
4. 总结
本文详细分析了 Spring Security 中 AuthenticationManager 的初始化和认证过程。熟悉这些内容有助于开发者实现复杂的认证逻辑,为项目集成 Spring Security 提供坚实的基础。欢迎关注「码农小胖哥」获取更多原创干货。
往期推荐:
你没见过Java台式计算机和Java操作系统吧
Spring Security 实战干货:UsernamePasswordAuthenticationFilter 源码分析
为什么我推荐Nginx作为后端服务器代理