AuthenticationSuccessHandler处理中的Authentication是什么,与传入AuthenticationManager#authenticate(Authentication authentication)中的 Authentication是一样的吗
UsernameAuthenticationFilter中调用AuthenticationManager#authenticate,其实调用的是DaoAuthenticationProvider的authenticate,在其父类AbstractUserDetailsAuthenticationProvider中定义了处理模板。其处理代码如下
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-
- String username = determineUsername(authentication);
- boolean cacheWasUsed = true;
- UserDetails user = this.userCache.getUserFromCache(username);
- if (user == null) {
- cacheWasUsed = false;
-
- user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
-
- }
-
- this.preAuthenticationChecks.check(user);
- additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
-
- this.postAuthenticationChecks.check(user);
- if (!cacheWasUsed) {
- this.userCache.putUserInCache(user);
- }
- Object principalToReturn = user;
- if (this.forcePrincipalAsString) {
- principalToReturn = user.getUsername();
- }
- return createSuccessAuthentication(principalToReturn, authentication, user);
- }
principalToReturn为retrieveUser返回的。DaoAuthenticationProvider的retrieveUser是通过UserDetailsService#loadUserByUserName得到UserDetails。
- protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
- throws AuthenticationException {
- prepareTimingAttackProtection();
-
- UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
- if (loadedUser == null) {
- throw new InternalAuthenticationServiceException(
- "UserDetailsService returned null, which is an interface contract violation");
- }
- return loadedUser;
- }
- }
然后创建新的Authentication,即以UserDetails作为principal。
- protected Authentication createSuccessAuthentication(Object principal, Authentication authentication,
- UserDetails user) {
- // Ensure we return the original credentials the user supplied,
- // so subsequent attempts are successful even with encoded passwords.
- // Also ensure we return the original getDetails(), so that future
- // authentication events after cache expiry contain the details
- UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.authenticated(principal,
- authentication.getCredentials(), this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
- result.setDetails(authentication.getDetails());
- this.logger.debug("Authenticated user");
- return result;
- }
AuthenticationSuccessHandler中的 authentication与AuthenticationManager#authenticate传入的不一样,AuthenticationSuccessHandler中的authentication是由UserDetails作为principal,AuthenticationManager#authenticate传入的authentication的credentials作为新authentication的credentials