博客
关于我
Spring Security 实战干货:理解AuthenticationManager
阅读量:422 次
发布时间:2019-03-06

本文共 3597 字,大约阅读时间需要 11 分钟。

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方法,这个我们已经在上一文分析了是通过AuthenticationManagerauthenticate方法进行认证逻辑的处理,接下来我们将重点分析这个接口来帮助我们了解Spring Seucirty的认证过程。

3. AuthenticationManager

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

3.1 AuthenticationManager的初始化流程

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

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

@Overrideprotected 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 获取更多资讯

转载地址:http://majuz.baihongyu.com/

你可能感兴趣的文章
MYSQL:基础——3N范式的表结构设计
查看>>
MYSQL:基础——触发器
查看>>
Mysql:连接报错“closing inbound before receiving peer‘s close_notify”
查看>>
mysqlbinlog报错unknown variable ‘default-character-set=utf8mb4‘
查看>>
mysqldump 参数--lock-tables浅析
查看>>
mysqldump 导出中文乱码
查看>>
mysqldump 导出数据库中每张表的前n条
查看>>
mysqldump: Got error: 1044: Access denied for user ‘xx’@’xx’ to database ‘xx’ when using LOCK TABLES
查看>>
Mysqldump参数大全(参数来源于mysql5.5.19源码)
查看>>
mysqldump备份时忽略某些表
查看>>
mysqldump实现数据备份及灾难恢复
查看>>
mysqldump数据库备份无法进行操作只能查询 --single-transaction
查看>>
mysqldump的一些用法
查看>>
mysqli
查看>>
MySQLIntegrityConstraintViolationException异常处理
查看>>
mysqlreport分析工具详解
查看>>
MySQLSyntaxErrorException: Unknown error 1146和SQLSyntaxErrorException: Unknown error 1146
查看>>
Mysql_Postgresql中_geometry数据操作_st_astext_GeomFromEWKT函数_在java中转换geometry的16进制数据---PostgreSQL工作笔记007
查看>>
mysql_real_connect 参数注意
查看>>
mysql_secure_installation初始化数据库报Access denied
查看>>