Zaimplementowałem pomysł zaproponowany przez Marcela Stör.
Dlaczego warto korzystać z tokenu, np. Podklasy uwierzytelniania? Czy funkcja Authentication.getPrincipal() nie zwraca instancji UserDetails w twoim przypadku?
Jeśli dostarczyłeś własną implementację UserDetails (jedną z użyciem metody setUsername()) podczas uwierzytelniania, że jesteś w domu, jeśli dobrze rozumiem twoją sprawę.
I chcę dzielić realizacji:
To jest UserDetails obiekt z modyfikowalny użytkownika. Zrobiłem to podklasę org.springframework.security.core.userdetails.User
, ponieważ używam go razem z Jdbc User Details Service, która normalnie tworzy te klasy.
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
/**
* Extension of {@link User} where it is possible to change the username.
*/
public class UpdateableUserDetails extends User {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 9034840503529809003L;
/**
* The user name that can be modified.
* It "overrides" the username field from class {@link User}.
*/
private String modfiableUsername;
/**
* Construct the <code>User</code> with the details required by
* {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider}.
*
* @param username the username presented to the
* <code>DaoAuthenticationProvider</code>
* @param password the password that should be presented to the
* <code>DaoAuthenticationProvider</code>
* @param enabled set to <code>true</code> if the user is enabled
* @param accountNonExpired set to <code>true</code> if the account has not
* expired
* @param credentialsNonExpired set to <code>true</code> if the credentials
* have not expired
* @param accountNonLocked set to <code>true</code> if the account is not
* locked
* @param authorities the authorities that should be granted to the caller
* if they presented the correct username and password and the user
* is enabled. Not null.
*
* @throws IllegalArgumentException if a <code>null</code> value was passed
* either as a parameter or as an element in the
* <code>GrantedAuthority</code> collection
*/
public UpdateableUserDetails(final String username, final String password, final boolean enabled,
final boolean accountNonExpired, final boolean credentialsNonExpired, final boolean accountNonLocked,
final Collection<? extends GrantedAuthority> authorities) throws IllegalArgumentException {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.modfiableUsername = username;
}
/**
* Calls the more complex constructor with all boolean arguments set to {@code true}.
* @param username the username presented to the
* <code>DaoAuthenticationProvider</code>
* @param password the password that should be presented to the
* <code>DaoAuthenticationProvider</code>
* @param authorities the authorities that should be granted to the caller
* if they presented the correct username and password and the user
* is enabled. Not null.
*/
public UpdateableUserDetails(final String username, final String password,
final Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
this.modfiableUsername = username;
}
/**
* Return the modifiable username instead of the fixed one.
*
* @return the username
*/
@Override
public String getUsername() {
return this.modfiableUsername;
}
public void setUsername(final String username) {
this.modfiableUsername = username;
}
/**
* Returns {@code true} if the supplied object is a {@code User} instance with the
* same {@code username} value.
* <p>
* In other words, the objects are equal if they have the same user name, representing the
* same principal.
*
* @param rhs the other object
* @return true if equals
*/
@Override
public boolean equals(final Object rhs) {
if (rhs instanceof User) {
return this.modfiableUsername.equals(((User) rhs).getUsername());
}
return false;
}
/**
* Returns the hashcode.
*
* In order not to get any problems with any hash sets that based on the fact that this hash is not changed
* over livetime and not to fail one of the constraints for {@link Object#hashCode()},
* this method always returns the same constant hash value.
*
* I expect that this is no such deal, because we expect not to have so many logged in users, so the hash sets
* that use this as an key will not get so slow.
*
* @return the hash
*/
@Override
public int hashCode() {
return 1;
}
/**
* Like {@link User#toString()}, but print the modifiable user name.
*
* @return the string representation with all details
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(": ");
sb.append("Username: ").append(this.modfiableUsername).append("; ");
sb.append("Password: [PROTECTED]; ");
sb.append("Enabled: ").append(isEnabled()).append("; ");
sb.append("AccountNonExpired: ").append(isAccountNonExpired()).append("; ");
sb.append("credentialsNonExpired: ").append(isCredentialsNonExpired()).append("; ");
sb.append("AccountNonLocked: ").append(isAccountNonLocked()).append("; ");
if (!getAuthorities().isEmpty()) {
sb.append("Granted Authorities: ");
boolean first = true;
for (GrantedAuthority auth : getAuthorities()) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(auth);
}
} else {
sb.append("Not granted any authorities");
}
return sb.toString();
}
}
podklasy dla UserDetailsService
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
/**
* Create {@link UpdateableUserDetails} instead of {@link org.springframework.security.core.userdetails.User} user details.
*/
public class JdbcDaoForUpdatableUsernames extends JdbcDaoImpl {
/**
* Instantiates a new jdbc dao for updatable usernames impl.
*
* @param privilegesService the privileges service
*/
public JdbcDaoForUpdatableUsernames(final PrivilegesService privilegesService) {
super(privilegesService);
}
/**
* Can be overridden to customize the creation of the final UserDetailsObject which is
* returned by the <tt>loadUserByUsername</tt> method.
*
* @param username the name originally passed to loadUserByUsername
* @param userFromUserQuery the object returned from the execution of the
* @param combinedAuthorities the combined array of authorities from all the authority loading queries.
* @return the final UserDetails which should be used in the system.
*/
@Override
protected UserDetails createUserDetails(final String username, final UserDetails userFromUserQuery,
final List<GrantedAuthority> combinedAuthorities) {
String returnUsername = userFromUserQuery.getUsername();
if (!isUsernameBasedPrimaryKey()) {
returnUsername = username;
}
return new UpdateableUserDetails(returnUsername,
userFromUserQuery.getPassword(),
userFromUserQuery.isEnabled(),
true,
true,
true,
combinedAuthorities);
}
}
Mam nadzieję, że ktoś może go używać zbyt.
Zaimplementowałem twój pomysł i zadziałało. http://stackoverflow.com/a/14174404/280244 – Ralph