• UsernameAuthenticationFilter授权成功后调用AuthenticationSuccessHandler时的解析


    1、问题

    AuthenticationSuccessHandler处理中的Authentication是什么,与传入AuthenticationManager#authenticate(Authentication authentication)中的 Authentication是一样的吗

    2、分析

    UsernameAuthenticationFilter中调用AuthenticationManager#authenticate,其实调用的是DaoAuthenticationProvider的authenticate,在其父类AbstractUserDetailsAuthenticationProvider中定义了处理模板。其处理代码如下

    1. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    2. String username = determineUsername(authentication);
    3. boolean cacheWasUsed = true;
    4. UserDetails user = this.userCache.getUserFromCache(username);
    5. if (user == null) {
    6. cacheWasUsed = false;
    7. user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
    8. }
    9. this.preAuthenticationChecks.check(user);
    10. additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
    11. this.postAuthenticationChecks.check(user);
    12. if (!cacheWasUsed) {
    13. this.userCache.putUserInCache(user);
    14. }
    15. Object principalToReturn = user;
    16. if (this.forcePrincipalAsString) {
    17. principalToReturn = user.getUsername();
    18. }
    19. return createSuccessAuthentication(principalToReturn, authentication, user);
    20. }

    principalToReturn为retrieveUser返回的。DaoAuthenticationProvider的retrieveUser是通过UserDetailsService#loadUserByUserName得到UserDetails。

    1. protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
    2. throws AuthenticationException {
    3. prepareTimingAttackProtection();
    4. UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
    5. if (loadedUser == null) {
    6. throw new InternalAuthenticationServiceException(
    7. "UserDetailsService returned null, which is an interface contract violation");
    8. }
    9. return loadedUser;
    10. }
    11. }

    然后创建新的Authentication,即以UserDetails作为principal。

    1. protected Authentication createSuccessAuthentication(Object principal, Authentication authentication,
    2. UserDetails user) {
    3. // Ensure we return the original credentials the user supplied,
    4. // so subsequent attempts are successful even with encoded passwords.
    5. // Also ensure we return the original getDetails(), so that future
    6. // authentication events after cache expiry contain the details
    7. UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(principal,
    8. authentication.getCredentials(), this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
    9. result.setDetails(authentication.getDetails());
    10. this.logger.debug("Authenticated user");
    11. return result;
    12. }

    3、结论

    AuthenticationSuccessHandler中的 authentication与AuthenticationManager#authenticate传入的不一样,AuthenticationSuccessHandler中的authentication是由UserDetails作为principal,AuthenticationManager#authenticate传入的authentication的credentials作为新authentication的credentials

  • 相关阅读:
    Web(1) 搭建漏洞环境(metasploitable2靶场/DVWA靶场)
    Vuex基本流程及 mapState mapMutations mapActions 简写形式
    安全性归约(构造 1)
    高版本springboot3.1配置Eureka客户端问题
    深入理解ElasticSearch集群:架构、高可用性与数据一致性
    毕设准备---HelloServlet
    Python图像处理
    【2】贪心算法-综述
    Docker私有仓库搭建
    canvas的基本使用
  • 原文地址:https://blog.csdn.net/wuli2496/article/details/126236328