Ver código fonte

SEC-1492: Added SimpleAuthoritiesMapper which provides a one-to-one authority mapping with case-conversion and the addition of a "role" prefix to the authority name.

Luke Taylor 14 anos atrás
pai
commit
5f6dab67e1

+ 101 - 0
core/src/main/java/org/springframework/security/core/authority/mapping/SimpleAuthorityMapper.java

@@ -0,0 +1,101 @@
+package org.springframework.security.core.authority.mapping;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.util.Assert;
+
+import java.util.*;
+
+/**
+ * Simple one-to-one {@code GrantedAuthoritiesMapper} which allows for case conversion of the authority name
+ * and the addition of a string prefix (which defaults to {@code ROLE_}).
+ *
+ * @author Luke Taylor
+ * @since 3.1
+ */
+public final class SimpleAuthorityMapper implements GrantedAuthoritiesMapper, InitializingBean {
+    private GrantedAuthority defaultAuthority;
+    private String prefix = "ROLE_";
+    private boolean convertToUpperCase = false;
+    private boolean convertToLowerCase = false;
+
+    public void afterPropertiesSet() throws Exception {
+        Assert.isTrue(!(convertToUpperCase && convertToLowerCase),
+                "Either convertToUpperCase or convertToLowerCase can be set to true, but not both");
+    }
+
+    /**
+     * Creates a mapping of the supplied authorities based on the case-conversion and prefix settings.
+     * The mapping will be one-to-one unless duplicates are produced during the conversion. If a default
+     * authority has been set, this will also be assigned to each mapping.
+     *
+     * @param authorities the original authorities
+     *
+     * @return the converted set of authorities
+     */
+    public Set<GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
+        HashSet<GrantedAuthority> mapped = new HashSet<GrantedAuthority>(authorities.size());
+        for (GrantedAuthority authority : authorities) {
+            mapped.add(mapAuthority(authority.getAuthority()));
+        }
+
+        if (defaultAuthority != null) {
+            mapped.add(defaultAuthority);
+        }
+
+        return mapped;
+    }
+
+    private GrantedAuthority mapAuthority(String name) {
+        if (convertToUpperCase) {
+            name = name.toUpperCase();
+        } else if (convertToLowerCase) {
+            name = name.toLowerCase();
+        }
+
+        if (prefix.length() > 0 && !name.startsWith(prefix)) {
+            name = prefix + name;
+        }
+
+        return new SimpleGrantedAuthority(name);
+    }
+
+    /**
+     * Sets the prefix which should be added to the authority name (if it doesn't already exist)
+     *
+     * @param prefix the prefix, typically to satisfy the behaviour of an {@code AccessDecisionVoter}.
+     */
+    public void setPrefix(String prefix) {
+        Assert.notNull(prefix, "prefix cannot be null");
+        this.prefix = prefix;
+    }
+
+    /**
+     * Whether to convert the authority value to upper case in the mapping.
+     *
+     * @param convertToUpperCase defaults to {@code false}
+     */
+    public void setConvertToUpperCase(boolean convertToUpperCase) {
+        this.convertToUpperCase = convertToUpperCase;
+    }
+
+    /**
+     * Whether to convert the authority value to lower case in the mapping.
+     *
+     * @param convertToLowerCase defaults to {@code false}
+     */
+    public void setConvertToLowerCase(boolean convertToLowerCase) {
+        this.convertToLowerCase = convertToLowerCase;
+    }
+
+    /**
+     * Sets a default authority to be assigned to all users
+     *
+     * @param authority the name of the authority to be assigned to all users.
+     */
+    public void setDefaultAuthority(String authority) {
+        Assert.hasText(authority, "The authority name cannot be set to an empty value");
+        this.defaultAuthority = new SimpleGrantedAuthority(authority);
+    }
+}

+ 76 - 0
core/src/test/java/org/springframework/security/core/authority/mapping/SimpleAuthoritiesMapperTests.java

@@ -0,0 +1,76 @@
+package org.springframework.security.core.authority.mapping;
+
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+
+import java.util.*;
+
+/**
+ * @author Luke Taylor
+ */
+public class SimpleAuthoritiesMapperTests {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void rejectsInvalidCaseConversionFlags() throws Exception {
+        SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
+        mapper.setConvertToLowerCase(true);
+        mapper.setConvertToUpperCase(true);
+        mapper.afterPropertiesSet();
+    }
+
+    @Test
+    public void defaultPrefixIsCorrectlyApplied() {
+        SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
+        Set<String> mapped = AuthorityUtils.authorityListToSet(
+                mapper.mapAuthorities(AuthorityUtils.createAuthorityList("AaA", "ROLE_bbb")));
+        assertTrue(mapped.contains("ROLE_AaA"));
+        assertTrue(mapped.contains("ROLE_bbb"));
+    }
+
+    @Test
+    public void caseIsConvertedCorrectly() {
+        SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
+        mapper.setPrefix("");
+        List<GrantedAuthority> toMap = AuthorityUtils.createAuthorityList("AaA", "Bbb");
+        Set<String> mapped = AuthorityUtils.authorityListToSet(mapper.mapAuthorities(toMap));
+        assertEquals(2, mapped.size());
+        assertTrue(mapped.contains("AaA"));
+        assertTrue(mapped.contains("Bbb"));
+
+        mapper.setConvertToLowerCase(true);
+        mapped = AuthorityUtils.authorityListToSet(mapper.mapAuthorities(toMap));
+        assertEquals(2, mapped.size());
+        assertTrue(mapped.contains("aaa"));
+        assertTrue(mapped.contains("bbb"));
+
+        mapper.setConvertToLowerCase(false);
+        mapper.setConvertToUpperCase(true);
+        mapped = AuthorityUtils.authorityListToSet(mapper.mapAuthorities(toMap));
+        assertEquals(2, mapped.size());
+        assertTrue(mapped.contains("AAA"));
+        assertTrue(mapped.contains("BBB"));
+    }
+
+    @Test
+    public void duplicatesAreRemoved() {
+        SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
+        mapper.setConvertToUpperCase(true);
+
+        Set<String> mapped = AuthorityUtils.authorityListToSet(
+                mapper.mapAuthorities(AuthorityUtils.createAuthorityList("AaA", "AAA")));
+        assertEquals(1, mapped.size());
+    }
+
+    @Test
+    public void defaultAuthorityIsAssignedIfSet() throws Exception {
+        SimpleAuthorityMapper mapper = new SimpleAuthorityMapper();
+        mapper.setDefaultAuthority("ROLE_USER");
+        Set<String> mapped = AuthorityUtils.authorityListToSet(mapper.mapAuthorities(AuthorityUtils.NO_AUTHORITIES));
+        assertEquals(1, mapped.size());
+        assertTrue(mapped.contains("ROLE_USER"));
+    }
+}