SEC-1304: Remove Comparable interface from GrantedAuthority to enable it to be imlemented by an enum.
This commit is contained in:
parent
1df82654e3
commit
e72cfd58d4
|
@ -18,7 +18,6 @@ package org.springframework.security.core;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.springframework.security.access.AccessDecisionManager;
|
import org.springframework.security.access.AccessDecisionManager;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an authority granted to an {@link Authentication} object.
|
* Represents an authority granted to an {@link Authentication} object.
|
||||||
|
@ -27,10 +26,6 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||||
* A <code>GrantedAuthority</code> must either represent itself as a
|
* A <code>GrantedAuthority</code> must either represent itself as a
|
||||||
* <code>String</code> or be specifically supported by an {@link
|
* <code>String</code> or be specifically supported by an {@link
|
||||||
* AccessDecisionManager}.
|
* AccessDecisionManager}.
|
||||||
* <p>
|
|
||||||
* Implementations must implement {@link Comparable} in order to ensure that
|
|
||||||
* array sorting logic guaranteed by {@link UserDetails#getAuthorities()} can
|
|
||||||
* be reliably implemented.
|
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
|
@ -41,11 +36,12 @@ public interface GrantedAuthority extends Serializable, Comparable<GrantedAuthor
|
||||||
/**
|
/**
|
||||||
* If the <code>GrantedAuthority</code> can be represented as a <code>String</code> and that
|
* If the <code>GrantedAuthority</code> can be represented as a <code>String</code> and that
|
||||||
* <code>String</code> is sufficient in precision to be relied upon for an access control decision by an {@link
|
* <code>String</code> is sufficient in precision to be relied upon for an access control decision by an {@link
|
||||||
* AccessDecisionManager} (or delegate), this method should return such a <code>String</code>.<p>If the
|
* AccessDecisionManager} (or delegate), this method should return such a <code>String</code>.
|
||||||
* <code>GrantedAuthority</code> cannot be expressed with sufficient precision as a <code>String</code>,
|
* <p>
|
||||||
|
* If the <code>GrantedAuthority</code> cannot be expressed with sufficient precision as a <code>String</code>,
|
||||||
* <code>null</code> should be returned. Returning <code>null</code> will require an
|
* <code>null</code> should be returned. Returning <code>null</code> will require an
|
||||||
* <code>AccessDecisionManager</code> (or delegate) to specifically support the <code>GrantedAuthority</code>
|
* <code>AccessDecisionManager</code> (or delegate) to specifically support the <code>GrantedAuthority</code>
|
||||||
* implementation, so returning <code>null</code> should be avoided unless actually required.</p>
|
* implementation, so returning <code>null</code> should be avoided unless actually required.
|
||||||
*
|
*
|
||||||
* @return a representation of the granted authority (or <code>null</code> if the granted authority cannot be
|
* @return a representation of the granted authority (or <code>null</code> if the granted authority cannot be
|
||||||
* expressed as a <code>String</code> with sufficient precision).
|
* expressed as a <code>String</code> with sufficient precision).
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
|
|
||||||
package org.springframework.security.core.userdetails;
|
package org.springframework.security.core.userdetails;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.Comparator;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ public class User implements UserDetails {
|
||||||
//~ Instance fields ================================================================================================
|
//~ Instance fields ================================================================================================
|
||||||
private final String password;
|
private final String password;
|
||||||
private final String username;
|
private final String username;
|
||||||
private final List<GrantedAuthority> authorities;
|
private final Set<GrantedAuthority> authorities;
|
||||||
private final boolean accountNonExpired;
|
private final boolean accountNonExpired;
|
||||||
private final boolean accountNonLocked;
|
private final boolean accountNonLocked;
|
||||||
private final boolean credentialsNonExpired;
|
private final boolean credentialsNonExpired;
|
||||||
|
@ -78,7 +78,7 @@ public class User implements UserDetails {
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if a <code>null</code> value was passed
|
* @throws IllegalArgumentException if a <code>null</code> value was passed
|
||||||
* either as a parameter or as an element in the
|
* either as a parameter or as an element in the
|
||||||
* <code>GrantedAuthority[]</code> array
|
* <code>GrantedAuthority</code> collection
|
||||||
*/
|
*/
|
||||||
public User(String username, String password, boolean enabled, boolean accountNonExpired,
|
public User(String username, String password, boolean enabled, boolean accountNonExpired,
|
||||||
boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities) {
|
boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities) {
|
||||||
|
@ -93,7 +93,7 @@ public class User implements UserDetails {
|
||||||
this.accountNonExpired = accountNonExpired;
|
this.accountNonExpired = accountNonExpired;
|
||||||
this.credentialsNonExpired = credentialsNonExpired;
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
this.accountNonLocked = accountNonLocked;
|
this.accountNonLocked = accountNonLocked;
|
||||||
this.authorities = Collections.unmodifiableList(sortAuthorities(authorities));
|
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
|
@ -105,7 +105,7 @@ public class User implements UserDetails {
|
||||||
|
|
||||||
User user = (User) rhs;
|
User user = (User) rhs;
|
||||||
|
|
||||||
// We rely on constructor to guarantee any User has non-null and >0
|
// We rely on constructor to guarantee any User has non-null
|
||||||
// authorities
|
// authorities
|
||||||
if (!authorities.equals(user.authorities)) {
|
if (!authorities.equals(user.authorities)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -134,10 +134,8 @@ public class User implements UserDetails {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int code = 9792;
|
int code = 9792;
|
||||||
|
|
||||||
if (this.getAuthorities() != null) {
|
for (GrantedAuthority authority : getAuthorities()) {
|
||||||
for (int i = 0; i < this.getAuthorities().size(); i++) {
|
code = code * (authority.hashCode() % 7);
|
||||||
code = code * (authorities.get(i).hashCode() % 7);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getPassword() != null) {
|
if (this.getPassword() != null) {
|
||||||
|
@ -183,19 +181,31 @@ public class User implements UserDetails {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<GrantedAuthority> sortAuthorities(Collection<GrantedAuthority> authorities) {
|
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<GrantedAuthority> authorities) {
|
||||||
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority array");
|
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
|
||||||
// Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-xxx)
|
// Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-717)
|
||||||
SortedSet<GrantedAuthority> sorter = new TreeSet<GrantedAuthority>();
|
SortedSet<GrantedAuthority> sortedAuthorities =
|
||||||
|
new TreeSet<GrantedAuthority>(new Comparator<GrantedAuthority>() {
|
||||||
|
public int compare(GrantedAuthority g1, GrantedAuthority g2) {
|
||||||
|
// Neither should ever be null as each entry is checked before adding it to the set.
|
||||||
|
// If the authority is null, it is a custom authority and should precede others.
|
||||||
|
if (g2.getAuthority() == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g1.getAuthority() == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g1.getAuthority().compareTo(g2.getAuthority());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (GrantedAuthority grantedAuthority : authorities) {
|
for (GrantedAuthority grantedAuthority : authorities) {
|
||||||
Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
|
Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
|
||||||
sorter.add(grantedAuthority);
|
sortedAuthorities.add(grantedAuthority);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<GrantedAuthority> sortedAuthorities = new ArrayList<GrantedAuthority>(sorter.size());
|
|
||||||
sortedAuthorities.addAll(sorter);
|
|
||||||
|
|
||||||
return sortedAuthorities;
|
return sortedAuthorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,12 +222,14 @@ public class User implements UserDetails {
|
||||||
if (this.getAuthorities() != null) {
|
if (this.getAuthorities() != null) {
|
||||||
sb.append("Granted Authorities: ");
|
sb.append("Granted Authorities: ");
|
||||||
|
|
||||||
for (int i = 0; i < authorities.size(); i++) {
|
boolean first = true;
|
||||||
if (i > 0) {
|
for (GrantedAuthority auth : authorities) {
|
||||||
|
if (!first) {
|
||||||
sb.append(", ");
|
sb.append(", ");
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append(authorities.get(i));
|
sb.append(auth);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sb.append("Not granted any authorities");
|
sb.append("Not granted any authorities");
|
||||||
|
|
Loading…
Reference in New Issue