Browse Source

SEC-717: Resolve UserDetails.getAuthorities() sort logic issue.

2.0.x
Ben Alex 18 years ago
parent
commit
6bc0585e4a
  1. 10
      core/src/main/java/org/springframework/security/GrantedAuthority.java
  2. 11
      core/src/main/java/org/springframework/security/GrantedAuthorityImpl.java
  3. 13
      core/src/main/java/org/springframework/security/userdetails/User.java
  4. 2
      core/src/main/java/org/springframework/security/userdetails/UserDetails.java
  5. 8
      core/src/test/java/org/springframework/security/GrantedAuthorityImplTests.java
  6. 7
      core/src/test/java/org/springframework/security/userdetails/UserTests.java

10
core/src/main/java/org/springframework/security/GrantedAuthority.java

@ -17,6 +17,8 @@ package org.springframework.security; @@ -17,6 +17,8 @@ package org.springframework.security;
import java.io.Serializable;
import org.springframework.security.userdetails.UserDetails;
/**
* Represents an authority granted to an {@link Authentication} object.
*
@ -25,11 +27,17 @@ import java.io.Serializable; @@ -25,11 +27,17 @@ import java.io.Serializable;
* <code>String</code> or be specifically supported by an {@link
* AccessDecisionManager}.
* </p>
*
* <p>
* Implementations must implement {@link Comparable} in order to ensure that
* array sorting logic guaranteed by {@link UserDetails#getAuthorities()} can
* be reliably implemented.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public interface GrantedAuthority extends Serializable {
public interface GrantedAuthority extends Serializable, Comparable {
//~ Methods ========================================================================================================
/**

11
core/src/main/java/org/springframework/security/GrantedAuthorityImpl.java

@ -17,6 +17,8 @@ package org.springframework.security; @@ -17,6 +17,8 @@ package org.springframework.security;
import java.io.Serializable;
import org.springframework.util.Assert;
/**
* Basic concrete implementation of a {@link GrantedAuthority}.<p>Stores a <code>String</code> representation of an
@ -35,6 +37,7 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable { @@ -35,6 +37,7 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
public GrantedAuthorityImpl(String role) {
super();
Assert.hasText(role, "A granted authority textual representation is required");
this.role = role;
}
@ -65,4 +68,12 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable { @@ -65,4 +68,12 @@ public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
public String toString() {
return this.role;
}
public int compareTo(Object o) {
if (o != null && o instanceof GrantedAuthority) {
GrantedAuthority rhs = (GrantedAuthority) o;
return this.role.compareTo(rhs.getAuthority());
}
return -1;
}
}

13
core/src/main/java/org/springframework/security/userdetails/User.java

@ -15,8 +15,11 @@ @@ -15,8 +15,11 @@
package org.springframework.security.userdetails;
import org.springframework.security.GrantedAuthority;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import org.springframework.security.GrantedAuthority;
import org.springframework.util.Assert;
@ -231,13 +234,15 @@ public class User implements UserDetails { @@ -231,13 +234,15 @@ public class User implements UserDetails {
protected void setAuthorities(GrantedAuthority[] authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority array");
// Ensure array iteration order is predictable (as per UserDetails.getAuthorities() contract and SEC-xxx)
SortedSet sorter = new TreeSet();
for (int i = 0; i < authorities.length; i++) {
Assert.notNull(authorities[i],
"Granted authority element " + i + " is null - GrantedAuthority[] cannot contain any null elements");
sorter.add(authorities[i]);
}
this.authorities = authorities;
this.authorities = (GrantedAuthority[]) sorter.toArray(new GrantedAuthority[sorter.size()]);
}
public String toString() {

2
core/src/main/java/org/springframework/security/userdetails/UserDetails.java

@ -54,7 +54,7 @@ public interface UserDetails extends Serializable { @@ -54,7 +54,7 @@ public interface UserDetails extends Serializable {
/**
* Returns the authorities granted to the user. Cannot return <code>null</code>.
*
* @return the authorities (never <code>null</code>)
* @return the authorities, sorted by natural key (never <code>null</code>)
*/
GrantedAuthority[] getAuthorities();

8
core/src/test/java/org/springframework/security/GrantedAuthorityImplTests.java

@ -76,14 +76,18 @@ public class GrantedAuthorityImplTests extends TestCase { @@ -76,14 +76,18 @@ public class GrantedAuthorityImplTests extends TestCase {
//~ Inner Classes ==================================================================================================
private class MockGrantedAuthorityImpl implements GrantedAuthority {
private class MockGrantedAuthorityImpl implements GrantedAuthority, Comparable {
private String role;
public MockGrantedAuthorityImpl(String role) {
this.role = role;
}
private MockGrantedAuthorityImpl() {
public int compareTo(Object o) {
return this.role.compareTo(((GrantedAuthority)o).getAuthority());
}
private MockGrantedAuthorityImpl() {
super();
}

7
core/src/test/java/org/springframework/security/userdetails/UserTests.java

@ -64,6 +64,11 @@ public class UserTests extends TestCase { @@ -64,6 +64,11 @@ public class UserTests extends TestCase {
new User("rod", "koala", true, true, true, true,
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")})));
// Equal as the new User will internally sort the GrantedAuthorities in the correct order, before running equals()
assertTrue(user1.equals(
new User("rod", "koala", true, true, true, true,
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_TWO"), new GrantedAuthorityImpl("ROLE_ONE")})));
assertFalse(user1.equals(
new User("DIFFERENT_USERNAME", "koala", true, true, true, true,
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")})));
@ -153,7 +158,7 @@ public class UserTests extends TestCase { @@ -153,7 +158,7 @@ public class UserTests extends TestCase {
public void testUserGettersSetter() throws Exception {
UserDetails user = new User("rod", "koala", true, true, true, true,
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")});
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_TWO"), new GrantedAuthorityImpl("ROLE_ONE")});
assertEquals("rod", user.getUsername());
assertEquals("koala", user.getPassword());
assertTrue(user.isEnabled());

Loading…
Cancel
Save