|
|
|
@ -51,12 +51,26 @@ import org.springframework.dao.DataAccessException; |
|
|
|
* <p> |
|
|
|
* <p> |
|
|
|
* Upon successful validation, a |
|
|
|
* Upon successful validation, a |
|
|
|
* <code>UsernamePasswordAuthenticationToken</code> will be created and |
|
|
|
* <code>UsernamePasswordAuthenticationToken</code> will be created and |
|
|
|
* returned to the caller. In addition, the {@link User} will be placed in the |
|
|
|
* returned to the caller. The token will include as its principal either a |
|
|
|
* {@link UserCache} so that subsequent requests with the same username can be |
|
|
|
* <code>String</code> representation of the username, or the {@link User} |
|
|
|
* validated without needing to query the {@link AuthenticationDao}. It should |
|
|
|
* that was returned from the authentication repository. Using |
|
|
|
* be noted that if a user appears to present an incorrect password, the |
|
|
|
* <code>String</code> is appropriate if a container adapter is being used, as |
|
|
|
* {@link AuthenticationDao} will be queried to confirm the most up-to-date |
|
|
|
* it expects <code>String</code> representations of the username. Using |
|
|
|
* password was used for comparison. |
|
|
|
* <code>User</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>User</code> provides additional flexibility, by default a |
|
|
|
|
|
|
|
* <code>User</code> is returned. To override this default, set the {@link |
|
|
|
|
|
|
|
* #setForcePrincipalAsString} to <code>true</code>. |
|
|
|
|
|
|
|
* </p> |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* <P> |
|
|
|
|
|
|
|
* Caching is handled via the <code>User</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> |
|
|
|
* </p> |
|
|
|
* |
|
|
|
* |
|
|
|
* <P> |
|
|
|
* <P> |
|
|
|
@ -79,6 +93,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, |
|
|
|
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); |
|
|
|
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); |
|
|
|
private SaltSource saltSource; |
|
|
|
private SaltSource saltSource; |
|
|
|
private UserCache userCache = new NullUserCache(); |
|
|
|
private UserCache userCache = new NullUserCache(); |
|
|
|
|
|
|
|
private boolean forcePrincipalAsString = false; |
|
|
|
|
|
|
|
|
|
|
|
//~ Methods ================================================================
|
|
|
|
//~ Methods ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
@ -95,6 +110,14 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, |
|
|
|
return authenticationDao; |
|
|
|
return authenticationDao; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setForcePrincipalAsString(boolean forcePrincipalAsString) { |
|
|
|
|
|
|
|
this.forcePrincipalAsString = forcePrincipalAsString; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public boolean isForcePrincipalAsString() { |
|
|
|
|
|
|
|
return forcePrincipalAsString; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Sets the PasswordEncoder instance to be used to encode and validate |
|
|
|
* Sets the PasswordEncoder instance to be used to encode and validate |
|
|
|
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by |
|
|
|
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by |
|
|
|
@ -148,13 +171,19 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, |
|
|
|
|
|
|
|
|
|
|
|
public Authentication authenticate(Authentication authentication) |
|
|
|
public Authentication authenticate(Authentication authentication) |
|
|
|
throws AuthenticationException { |
|
|
|
throws AuthenticationException { |
|
|
|
|
|
|
|
// Determine username
|
|
|
|
|
|
|
|
String username = authentication.getPrincipal().toString(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (authentication.getPrincipal() instanceof User) { |
|
|
|
|
|
|
|
username = ((User) authentication.getPrincipal()).getUsername(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean cacheWasUsed = true; |
|
|
|
boolean cacheWasUsed = true; |
|
|
|
User user = this.userCache.getUserFromCache(authentication.getPrincipal() |
|
|
|
User user = this.userCache.getUserFromCache(username); |
|
|
|
.toString()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (user == null) { |
|
|
|
if (user == null) { |
|
|
|
cacheWasUsed = false; |
|
|
|
cacheWasUsed = false; |
|
|
|
user = getUserFromBackend(authentication); |
|
|
|
user = getUserFromBackend(username); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!user.isEnabled()) { |
|
|
|
if (!user.isEnabled()) { |
|
|
|
@ -170,7 +199,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, |
|
|
|
// Password incorrect, so ensure we're using most current password
|
|
|
|
// Password incorrect, so ensure we're using most current password
|
|
|
|
if (cacheWasUsed) { |
|
|
|
if (cacheWasUsed) { |
|
|
|
cacheWasUsed = false; |
|
|
|
cacheWasUsed = false; |
|
|
|
user = getUserFromBackend(authentication); |
|
|
|
user = getUserFromBackend(username); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!isPasswordCorrect(authentication, user)) { |
|
|
|
if (!isPasswordCorrect(authentication, user)) { |
|
|
|
@ -194,9 +223,15 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object principalToReturn = user; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (forcePrincipalAsString) { |
|
|
|
|
|
|
|
principalToReturn = user.getUsername(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Ensure we return the original credentials the user supplied,
|
|
|
|
// Ensure we return the original credentials the user supplied,
|
|
|
|
// so subsequent attempts are successful even with encoded passwords
|
|
|
|
// so subsequent attempts are successful even with encoded passwords
|
|
|
|
return new UsernamePasswordAuthenticationToken(user.getUsername(), |
|
|
|
return new UsernamePasswordAuthenticationToken(principalToReturn, |
|
|
|
authentication.getCredentials(), user.getAuthorities()); |
|
|
|
authentication.getCredentials(), user.getAuthorities()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -220,10 +255,9 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, |
|
|
|
authentication.getCredentials().toString(), salt); |
|
|
|
authentication.getCredentials().toString(), salt); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private User getUserFromBackend(Authentication authentication) { |
|
|
|
private User getUserFromBackend(String username) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
return this.authenticationDao.loadUserByUsername(authentication.getPrincipal() |
|
|
|
return this.authenticationDao.loadUserByUsername(username); |
|
|
|
.toString()); |
|
|
|
|
|
|
|
} catch (UsernameNotFoundException notFound) { |
|
|
|
} catch (UsernameNotFoundException notFound) { |
|
|
|
throw new BadCredentialsException("Bad credentials presented"); |
|
|
|
throw new BadCredentialsException("Bad credentials presented"); |
|
|
|
} catch (DataAccessException repositoryProblem) { |
|
|
|
} catch (DataAccessException repositoryProblem) { |
|
|
|
|