| package com.mzl.flower.config.security.provider; | 
|   | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.factory.InitializingBean; | 
| import org.springframework.context.MessageSource; | 
| import org.springframework.context.MessageSourceAware; | 
| import org.springframework.context.support.MessageSourceAccessor; | 
| import org.springframework.security.authentication.*; | 
| import org.springframework.security.core.Authentication; | 
| import org.springframework.security.core.AuthenticationException; | 
| import org.springframework.security.core.SpringSecurityMessageSource; | 
| import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; | 
| import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper; | 
| import org.springframework.security.core.userdetails.UserCache; | 
| import org.springframework.security.core.userdetails.UserDetails; | 
| import org.springframework.security.core.userdetails.UserDetailsChecker; | 
| import org.springframework.security.core.userdetails.UsernameNotFoundException; | 
| import org.springframework.security.core.userdetails.cache.NullUserCache; | 
| import org.springframework.util.Assert; | 
|   | 
| @Slf4j | 
| public abstract class SelfAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { | 
|   | 
|     protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); | 
|     private UserCache userCache = new NullUserCache(); | 
|     private boolean forcePrincipalAsString = false; | 
|     protected boolean hideUserNotFoundExceptions = true; | 
|     private UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks(); | 
|     private UserDetailsChecker postAuthenticationChecks = new DefaultPostAuthenticationChecks(); | 
|     private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); | 
|   | 
|   | 
|     protected abstract void additionalAuthenticationChecks(UserDetails userDetails, | 
|                                                            Authentication authentication) | 
|             throws AuthenticationException; | 
|      | 
|     @Override | 
|     public void afterPropertiesSet() throws Exception { | 
|         Assert.notNull(this.userCache, "A user cache must be set"); | 
|         Assert.notNull(this.messages, "A message source must be set"); | 
|         doAfterPropertiesSet(); | 
|     } | 
|   | 
|     @Override | 
|     public Authentication authenticate(Authentication authentication) throws AuthenticationException { | 
|         String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName(); | 
|   | 
|         boolean cacheWasUsed = true; | 
|         UserDetails user = this.userCache.getUserFromCache(username); | 
|   | 
|         if (user == null) { | 
|             cacheWasUsed = false; | 
|   | 
|             try { | 
|                 user = retrieveUser(username, authentication); | 
|             } | 
|             catch (UsernameNotFoundException notFound) { | 
|                 log.debug("User '" + username + "' not found"); | 
|   | 
|                 if (hideUserNotFoundExceptions) { | 
|                     throw new BadCredentialsException(messages.getMessage( | 
|                             "AbstractUserDetailsAuthenticationProvider.badCredentials", | 
|                             "Bad credentials")); | 
|                 } | 
|                 else { | 
|                     throw notFound; | 
|                 } | 
|             } | 
|   | 
|             Assert.notNull(user, | 
|                     "retrieveUser returned null - a violation of the interface contract"); | 
|         } | 
|   | 
|         try { | 
|             preAuthenticationChecks.check(user); | 
|             additionalAuthenticationChecks(user, authentication); | 
|         } | 
|         catch (AuthenticationException exception) { | 
|             if (cacheWasUsed) { | 
|                 cacheWasUsed = false; | 
|                 user = retrieveUser(username, authentication); | 
|                 preAuthenticationChecks.check(user); | 
|                 additionalAuthenticationChecks(user, authentication); | 
|             } | 
|             else { | 
|                 throw exception; | 
|             } | 
|         } | 
|   | 
|         postAuthenticationChecks.check(user); | 
|   | 
|         if (!cacheWasUsed) { | 
|             this.userCache.putUserInCache(user); | 
|         } | 
|   | 
|         Object principalToReturn = user; | 
|   | 
|         if (forcePrincipalAsString) { | 
|             principalToReturn = user.getUsername(); | 
|         } | 
|   | 
|         return createSuccessAuthentication(principalToReturn, authentication, user); | 
|     } | 
|   | 
|     protected abstract Authentication createSuccessAuthentication(Object principal, | 
|                                                          Authentication authentication, UserDetails user); | 
|   | 
|     protected void doAfterPropertiesSet() throws Exception { | 
|     } | 
|   | 
|     public UserCache getUserCache() { | 
|         return userCache; | 
|     } | 
|   | 
|     public boolean isForcePrincipalAsString() { | 
|         return forcePrincipalAsString; | 
|     } | 
|   | 
|     public boolean isHideUserNotFoundExceptions() { | 
|         return hideUserNotFoundExceptions; | 
|     } | 
|   | 
|     protected abstract UserDetails retrieveUser(String username, Authentication authentication) throws AuthenticationException; | 
|   | 
|     public void setForcePrincipalAsString(boolean forcePrincipalAsString) { | 
|         this.forcePrincipalAsString = forcePrincipalAsString; | 
|     } | 
|   | 
|     public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) { | 
|         this.hideUserNotFoundExceptions = hideUserNotFoundExceptions; | 
|     } | 
|   | 
|     public void setMessageSource(MessageSource messageSource) { | 
|         this.messages = new MessageSourceAccessor(messageSource); | 
|     } | 
|   | 
|     public void setUserCache(UserCache userCache) { | 
|         this.userCache = userCache; | 
|     } | 
|   | 
|     protected UserDetailsChecker getPreAuthenticationChecks() { | 
|         return preAuthenticationChecks; | 
|     } | 
|   | 
|     public void setPreAuthenticationChecks(UserDetailsChecker preAuthenticationChecks) { | 
|         this.preAuthenticationChecks = preAuthenticationChecks; | 
|     } | 
|   | 
|     protected UserDetailsChecker getPostAuthenticationChecks() { | 
|         return postAuthenticationChecks; | 
|     } | 
|   | 
|     public void setPostAuthenticationChecks(UserDetailsChecker postAuthenticationChecks) { | 
|         this.postAuthenticationChecks = postAuthenticationChecks; | 
|     } | 
|   | 
|     public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) { | 
|         this.authoritiesMapper = authoritiesMapper; | 
|     } | 
|   | 
|     private class DefaultPreAuthenticationChecks implements UserDetailsChecker { | 
|         public void check(UserDetails user) { | 
|             if (!user.isAccountNonLocked()) { | 
|                 log.debug("User account is locked"); | 
|   | 
|                 throw new LockedException(messages.getMessage( | 
|                         "AbstractUserDetailsAuthenticationProvider.locked", | 
|                         "User account is locked")); | 
|             } | 
|   | 
|             if (!user.isEnabled()) { | 
|                 log.debug("User account is disabled"); | 
|   | 
|                 throw new DisabledException(messages.getMessage( | 
|                         "AbstractUserDetailsAuthenticationProvider.disabled", | 
|                         "User is disabled")); | 
|             } | 
|   | 
|             if (!user.isAccountNonExpired()) { | 
|                 log.debug("User account is expired"); | 
|   | 
|                 throw new AccountExpiredException(messages.getMessage( | 
|                         "AbstractUserDetailsAuthenticationProvider.expired", | 
|                         "User account has expired")); | 
|             } | 
|         } | 
|     } | 
|   | 
|     private class DefaultPostAuthenticationChecks implements UserDetailsChecker { | 
|         public void check(UserDetails user) { | 
|             if (!user.isCredentialsNonExpired()) { | 
|                 log.debug("User account credentials have expired"); | 
|   | 
|                 throw new CredentialsExpiredException(messages.getMessage( | 
|                         "AbstractUserDetailsAuthenticationProvider.credentialsExpired", | 
|                         "User credentials have expired")); | 
|             } | 
|         } | 
|     } | 
| } |