|
@@ -51,12 +51,26 @@ import org.springframework.dao.DataAccessException;
|
|
|
* <p>
|
|
|
* Upon successful validation, a
|
|
|
* <code>UsernamePasswordAuthenticationToken</code> will be created and
|
|
|
- * returned to the caller. In addition, the {@link User} will be placed in the
|
|
|
- * {@link UserCache} so 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.
|
|
|
+ * returned to the caller. The token will include as its principal either a
|
|
|
+ * <code>String</code> representation of the username, or the {@link User}
|
|
|
+ * 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>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>
|
|
@@ -79,6 +93,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|
|
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
|
|
private SaltSource saltSource;
|
|
|
private UserCache userCache = new NullUserCache();
|
|
|
+ private boolean forcePrincipalAsString = false;
|
|
|
|
|
|
//~ Methods ================================================================
|
|
|
|
|
@@ -95,6 +110,14 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|
|
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
|
|
|
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
|
|
@@ -148,13 +171,19 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|
|
|
|
|
public Authentication authenticate(Authentication authentication)
|
|
|
throws AuthenticationException {
|
|
|
+ // Determine username
|
|
|
+ String username = authentication.getPrincipal().toString();
|
|
|
+
|
|
|
+ if (authentication.getPrincipal() instanceof User) {
|
|
|
+ username = ((User) authentication.getPrincipal()).getUsername();
|
|
|
+ }
|
|
|
+
|
|
|
boolean cacheWasUsed = true;
|
|
|
- User user = this.userCache.getUserFromCache(authentication.getPrincipal()
|
|
|
- .toString());
|
|
|
+ User user = this.userCache.getUserFromCache(username);
|
|
|
|
|
|
if (user == null) {
|
|
|
cacheWasUsed = false;
|
|
|
- user = getUserFromBackend(authentication);
|
|
|
+ user = getUserFromBackend(username);
|
|
|
}
|
|
|
|
|
|
if (!user.isEnabled()) {
|
|
@@ -170,7 +199,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|
|
// Password incorrect, so ensure we're using most current password
|
|
|
if (cacheWasUsed) {
|
|
|
cacheWasUsed = false;
|
|
|
- user = getUserFromBackend(authentication);
|
|
|
+ user = getUserFromBackend(username);
|
|
|
}
|
|
|
|
|
|
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,
|
|
|
// so subsequent attempts are successful even with encoded passwords
|
|
|
- return new UsernamePasswordAuthenticationToken(user.getUsername(),
|
|
|
+ return new UsernamePasswordAuthenticationToken(principalToReturn,
|
|
|
authentication.getCredentials(), user.getAuthorities());
|
|
|
}
|
|
|
|
|
@@ -220,10 +255,9 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|
|
authentication.getCredentials().toString(), salt);
|
|
|
}
|
|
|
|
|
|
- private User getUserFromBackend(Authentication authentication) {
|
|
|
+ private User getUserFromBackend(String username) {
|
|
|
try {
|
|
|
- return this.authenticationDao.loadUserByUsername(authentication.getPrincipal()
|
|
|
- .toString());
|
|
|
+ return this.authenticationDao.loadUserByUsername(username);
|
|
|
} catch (UsernameNotFoundException notFound) {
|
|
|
throw new BadCredentialsException("Bad credentials presented");
|
|
|
} catch (DataAccessException repositoryProblem) {
|