| 
					
				 | 
			
			
				@@ -0,0 +1,280 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Copyright 2004, 2005 Acegi Technology Pty Limited 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Licensed under the Apache License, Version 2.0 (the "License"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * you may not use this file except in compliance with the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * You may obtain a copy of the License at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     http://www.apache.org/licenses/LICENSE-2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Unless required by applicable law or agreed to in writing, software 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * distributed under the License is distributed on an "AS IS" BASIS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * See the License for the specific language governing permissions and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * limitations under the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package net.sf.acegisecurity.providers.dao; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.AccountExpiredException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.Authentication; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.AuthenticationException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.CredentialsExpiredException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.DisabledException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.LockedException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.UserDetails; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.providers.AuthenticationProvider; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import net.sf.acegisecurity.providers.dao.cache.NullUserCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.beans.factory.InitializingBean; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.util.Assert; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * A base {@link AuthenticationProvider} that allows subclasses to override and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * work with {@link net.sf.acegisecurity.UserDetails} objects. The class is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * designed to respond to {@link UsernamePasswordAuthenticationToken} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * authentication requests. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Upon successful validation, a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <code>UsernamePasswordAuthenticationToken</code> will be created and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * returned to the caller. The token will include as its principal either a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <code>String</code> representation of the username, or the {@link 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * UserDetails} that was returned from the authentication repository. Using 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <code>String</code> is appropriate if a container adapter is being used, as 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * it expects <code>String</code> representations of the username. Using 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <code>UserDetails</code> is appropriate if you require access to additional 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * properties of the authenticated user, such as email addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * human-friendly names etc. As container adapters are not recommended to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * used, and <code>UserDetails</code> implementations provide additional 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * flexibility, by default a <code>UserDetails</code> is returned. To override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * this default, set the {@link #setForcePrincipalAsString} to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <code>true</code>. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <P> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Caching is handled via the <code>UserDetails</code> object being placed in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * the {@link UserCache}. This ensures that subsequent requests with the same 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * username can be validated without needing to query the {@link 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * AuthenticationDao}. It should be noted that if a user appears to present an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * incorrect password, the {@link AuthenticationDao} will be queried to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * confirm the most up-to-date password was used for comparison. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @author Ben Alex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @version $Id$ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public abstract class AbstractUserDetailsAuthenticationProvider 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    implements AuthenticationProvider, InitializingBean { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //~ Instance fields ======================================================== 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private UserCache userCache = new NullUserCache(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private boolean forcePrincipalAsString = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //~ Methods ================================================================ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void setForcePrincipalAsString(boolean forcePrincipalAsString) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.forcePrincipalAsString = forcePrincipalAsString; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public boolean isForcePrincipalAsString() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return forcePrincipalAsString; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public void setUserCache(UserCache userCache) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.userCache = userCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public UserCache getUserCache() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return userCache; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public final void afterPropertiesSet() throws Exception { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Assert.notNull(this.userCache, "A user cache must be set"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        doAfterPropertiesSet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public Authentication authenticate(Authentication authentication) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        throws AuthenticationException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            authentication, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "Only UsernamePasswordAuthenticationToken is supported"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Determine username 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String username = (authentication.getPrincipal() == null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? "NONE_PROVIDED" : authentication.getName(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boolean cacheWasUsed = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        UserDetails user = this.userCache.getUserFromCache(username); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (user == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cacheWasUsed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            user = retrieveUser(username, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    (UsernamePasswordAuthenticationToken) authentication); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Assert.notNull(user, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "retrieveUser returned null - a violation of the interface contract"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!user.isAccountNonLocked()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new LockedException("User account is locked"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!user.isEnabled()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new DisabledException("User is disabled"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!user.isAccountNonExpired()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new AccountExpiredException("User account has expired"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // This check must come here, as we don't want to tell users 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // about account status unless they presented the correct credentials 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            additionalAuthenticationChecks(user, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (UsernamePasswordAuthenticationToken) authentication); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (AuthenticationException exception) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // There was a problem, so try again after checking we're using latest data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            cacheWasUsed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            user = retrieveUser(username, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    (UsernamePasswordAuthenticationToken) authentication); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            additionalAuthenticationChecks(user, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (UsernamePasswordAuthenticationToken) authentication); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!user.isCredentialsNonExpired()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new CredentialsExpiredException( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "User credentials have expired"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!cacheWasUsed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.userCache.putUserInCache(user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Object principalToReturn = user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (forcePrincipalAsString) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            principalToReturn = user.getUsername(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return createSuccessAuthentication(principalToReturn, authentication, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            user); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public boolean supports(Class authentication) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Allows subclasses to perform any additional checks of a returned (or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * cached) <code>UserDetails</code> for a given authentication request. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Generally a subclass will at least compare the {@link 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Authentication#getCredentials()} with a {@link 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * UserDetails#getPassword()}. If custom logic is needed to compare 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * additional properties of <code>UserDetails</code> and/or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>UsernamePasswordAuthenticationToken</code>, these should also 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * appear in this method. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param userDetails as retrieved from the {@link #retrieveUser(String, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *        UsernamePasswordAuthenticationToken)} or <code>UserCache</code> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param authentication the current request that needs to be authenticated 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @throws AuthenticationException AuthenticationException if the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         credentials could not be validated (generally a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         <code>BadCredentialsException</code>, an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         <code>AuthenticationServiceException</code>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected abstract void additionalAuthenticationChecks( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        UserDetails userDetails, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        UsernamePasswordAuthenticationToken authentication) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        throws AuthenticationException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected void doAfterPropertiesSet() throws Exception {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Allows subclasses to actually retrieve the <code>UserDetails</code> from 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * an implementation-specific location, with the option of throwing an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>AuthenticationException</code> immediately if the presented 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * credentials are incorrect (this is especially useful if it is necessary 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * to bind to a resource as the user in order to obtain or generate a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>UserDetails</code>). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Subclasses are not required to perform any caching, as the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>AbstractUserDetailsAuthenticationProvider</code> will by default 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * cache the <code>UserDetails</code>. The caching of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>UserDetails</code> does present additional complexity as this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * means subsequent requests that rely on the cache will need to still 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * have their credentials validated, even if the correctness of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * credentials was assured by subclasses adopting a binding-based strategy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * in this method. Accordingly it is important that subclasses either 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * disable caching (if they want to ensure that this method is the only 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * method that is capable of authenticating a request, as no 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>UserDetails</code> will ever be cached) or ensure subclasses 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * implement {@link #additionalAuthenticationChecks(UserDetails, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * UsernamePasswordAuthenticationToken)} to compare the credentials of a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * cached <code>UserDetails</code> with subsequent authentication 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * requests. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Most of the time subclasses will not perform credentials inspection in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * this method, instead performing it in {@link 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * #additionalAuthenticationChecks(UserDetails, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * UsernamePasswordAuthenticationToken)} so that code related to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * credentials validation need not be duplicated across two methods. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param username The username to retrieve 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param authentication The authentication request, which subclasses 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *        <em>may</em> need to perform a binding-based retrieval of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *        <code>UserDetails</code> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return the user information (never <code>null</code> - instead an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         exception should the thrown) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @throws AuthenticationException if the credentials could not be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         validated (generally a <code>BadCredentialsException</code>, an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         <code>AuthenticationServiceException</code> or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *         <code>UserNotFoundException</code>) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected abstract UserDetails retrieveUser(String username, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        UsernamePasswordAuthenticationToken authentication) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        throws AuthenticationException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Creates a successful {@link Authentication} object. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <P> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Protected so subclasses can override. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <P> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Subclasses will usually store the original credentials the user supplied 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * (not salted or encoded passwords) in the returned 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * <code>Authentication</code> object. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param principal that should be the principal in the returned object 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *        (defined by the {@link #isForcePrincipalAsString()} method) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param authentication that was presented to the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *        <code>DaoAuthenticationProvider</code> for validation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param user that was loaded by the <code>AuthenticationDao</code> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return the successful authentication token 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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 = new UsernamePasswordAuthenticationToken(principal, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                authentication.getCredentials(), user.getAuthorities()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        result.setDetails((authentication.getDetails() != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? authentication.getDetails() : null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |