mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +00:00 
			
		
		
		
	SEC-717: Resolve UserDetails.getAuthorities() sort logic issue.
This commit is contained in:
		
							parent
							
								
									820c529809
								
							
						
					
					
						commit
						6bc0585e4a
					
				| @ -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. | ||||
|  * | ||||
| @ -26,10 +28,16 @@ import java.io.Serializable; | ||||
|  * 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 ======================================================================================================== | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -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 { | ||||
| 
 | ||||
|     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 { | ||||
|     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; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -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 { | ||||
| 
 | ||||
|     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() { | ||||
|  | ||||
| @ -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(); | ||||
| 
 | ||||
|  | ||||
| @ -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(); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -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 { | ||||
| 
 | ||||
|     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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user