Quellcode durchsuchen

SEC-863: Hierarchical roles should use the interface GrantedAuthority. Applied submitted patch.

Luke Taylor vor 16 Jahren
Ursprung
Commit
305ce125fb

+ 233 - 198
core/src/main/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.java

@@ -1,198 +1,233 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.hierarchicalroles;
-
-
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.GrantedAuthorityImpl;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import java.util.*;
-
-/**
- * <p>
- * This class defines a role hierarchy for use with the UserDetailsServiceWrapper.
- * </p>
- * <p>
- * Here is an example configuration of a role hierarchy (hint: read the "&gt;" sign as "includes"):
-<pre>
-        &lt;property name="hierarchy"&gt;
-            &lt;value&gt;
-                ROLE_A &gt; ROLE_B
-                ROLE_B &gt; ROLE_AUTHENTICATED
-                ROLE_AUTHENTICATED &gt; ROLE_UNAUTHENTICATED
-            &lt;/value&gt;
-        &lt;/property&gt;
-</pre>
-</p>
- * <p>
- * Explanation of the above:<br>
- * In effect every user with ROLE_A also has ROLE_B, ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;<br>
- * every user with ROLE_B also has ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;<br>
- * every user with ROLE_AUTHENTICATED also has ROLE_UNAUTHENTICATED.
- * </p>
- * <p>
- * Hierarchical Roles will dramatically shorten your access rules (and also make the access rules much more elegant).
- * </p>
- * <p>
- * Consider this access rule for Spring Security's RoleVoter (background: every user that is authenticated should be
- * able to log out):<br>
- * /logout.html=ROLE_A,ROLE_B,ROLE_AUTHENTICATED<br>
- * With hierarchical roles this can now be shortened to:<br>
- * /logout.html=ROLE_AUTHENTICATED<br>
- * In addition to shorter rules this will also make your access rules more readable and your intentions clearer.
- * </p>
- *
- * @author Michael Mayr
- *
- */
-public class RoleHierarchyImpl implements RoleHierarchy {
-
-    private static final Log logger = LogFactory.getLog(RoleHierarchyImpl.class);
-
-    private String roleHierarchyStringRepresentation = null;
-
-    /**
-     * rolesReachableInOneStepMap is a Map that under the key of a specific role name contains a set of all roles
-     * reachable from this role in 1 step
-     */
-    private Map<GrantedAuthority, Set<GrantedAuthority>> rolesReachableInOneStepMap = null;
-
-    /**
-     * rolesReachableInOneOrMoreStepsMap is a Map that under the key of a specific role name contains a set of all
-     * roles reachable from this role in 1 or more steps
-     */
-    private Map<GrantedAuthority, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap = null;
-
-    /**
-     * Set the role hierarchy and pre-calculate for every role the set of all reachable roles, i.e. all roles lower in
-     * the hierarchy of every given role. Pre-calculation is done for performance reasons (reachable roles can then be
-     * calculated in O(1) time).
-     * During pre-calculation, cycles in role hierarchy are detected and will cause a
-     * <tt>CycleInRoleHierarchyException</tt> to be thrown.
-     *
-     * @param roleHierarchyStringRepresentation - String definition of the role hierarchy.
-     */
-    public void setHierarchy(String roleHierarchyStringRepresentation) {
-        this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation;
-
-        logger.debug("setHierarchy() - The following role hierarchy was set: " + roleHierarchyStringRepresentation);
-
-        buildRolesReachableInOneStepMap();
-        buildRolesReachableInOneOrMoreStepsMap();
-    }
-
-    public List<GrantedAuthority> getReachableGrantedAuthorities(List<GrantedAuthority> authorities) {
-        if (authorities == null || authorities.isEmpty()) {
-            return null;
-        }
-
-        Set<GrantedAuthority> reachableRoles = new HashSet<GrantedAuthority>();
-
-        for (GrantedAuthority authority : authorities) {
-            reachableRoles.add(authority);
-            Set<GrantedAuthority> additionalReachableRoles = rolesReachableInOneOrMoreStepsMap.get(authority);
-            if (additionalReachableRoles != null) {
-                reachableRoles.addAll(additionalReachableRoles);
-            }
-        }
-
-        if (logger.isDebugEnabled()) {
-            logger.debug("getReachableGrantedAuthorities() - From the roles " + authorities
-                    + " one can reach " + reachableRoles + " in zero or more steps.");
-        }
-
-        List<GrantedAuthority> reachableRoleList = new ArrayList<GrantedAuthority>(reachableRoles.size());
-        reachableRoleList.addAll(reachableRoles);
-
-        return reachableRoleList;
-    }
-
-    /**
-     * Parse input and build the map for the roles reachable in one step: the higher role will become a key that
-     * references a set of the reachable lower roles.
-     */
-    private void buildRolesReachableInOneStepMap() {
-        Pattern pattern = Pattern.compile("(\\s*([^\\s>]+)\\s*\\>\\s*([^\\s>]+))");
-
-        Matcher roleHierarchyMatcher = pattern.matcher(roleHierarchyStringRepresentation);
-        rolesReachableInOneStepMap = new HashMap<GrantedAuthority, Set<GrantedAuthority>>();
-
-        while (roleHierarchyMatcher.find()) {
-            GrantedAuthority higherRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(2));
-            GrantedAuthority lowerRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(3));
-            Set<GrantedAuthority> rolesReachableInOneStepSet = null;
-
-            if (!rolesReachableInOneStepMap.containsKey(higherRole)) {
-                rolesReachableInOneStepSet = new HashSet<GrantedAuthority>();
-                rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet);
-            } else {
-                rolesReachableInOneStepSet = rolesReachableInOneStepMap.get(higherRole);
-            }
-            rolesReachableInOneStepSet.add(lowerRole);
-
-            logger.debug("buildRolesReachableInOneStepMap() - From role "
-                    + higherRole + " one can reach role " + lowerRole + " in one step.");
-        }
-    }
-
-    /**
-     * For every higher role from rolesReachableInOneStepMap store all roles that are reachable from it in the map of
-     * roles reachable in one or more steps. (Or throw a CycleInRoleHierarchyException if a cycle in the role
-     * hierarchy definition is detected)
-     */
-    private void buildRolesReachableInOneOrMoreStepsMap() {
-        rolesReachableInOneOrMoreStepsMap = new HashMap<GrantedAuthority, Set<GrantedAuthority>>();
-        // iterate over all higher roles from rolesReachableInOneStepMap
-
-        for(GrantedAuthority role : rolesReachableInOneStepMap.keySet()) {
-            Set<GrantedAuthority> rolesToVisitSet = new HashSet<GrantedAuthority>();
-
-            if (rolesReachableInOneStepMap.containsKey(role)) {
-                rolesToVisitSet.addAll(rolesReachableInOneStepMap.get(role));
-            }
-
-            Set<GrantedAuthority> visitedRolesSet = new HashSet<GrantedAuthority>();
-
-            while (!rolesToVisitSet.isEmpty()) {
-                // take a role from the rolesToVisit set
-                GrantedAuthority aRole = (GrantedAuthority) rolesToVisitSet.iterator().next();
-                rolesToVisitSet.remove(aRole);
-                visitedRolesSet.add(aRole);
-                if (rolesReachableInOneStepMap.containsKey(aRole)) {
-                    Set<GrantedAuthority> newReachableRoles = rolesReachableInOneStepMap.get(aRole);
-
-                    // definition of a cycle: you can reach the role you are starting from
-                    if (rolesToVisitSet.contains(role) || visitedRolesSet.contains(role)) {
-                        throw new CycleInRoleHierarchyException();
-                    } else {
-                         // no cycle
-                        rolesToVisitSet.addAll(newReachableRoles);
-                    }
-                }
-            }
-            rolesReachableInOneOrMoreStepsMap.put(role, visitedRolesSet);
-
-            logger.debug("buildRolesReachableInOneOrMoreStepsMap() - From role "
-                    + role + " one can reach " + visitedRolesSet + " in one or more steps.");
-        }
-
-    }
-
-}
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.access.hierarchicalroles;
+
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.GrantedAuthorityImpl;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import java.util.*;
+
+/**
+ * <p>
+ * This class defines a role hierarchy for use with the UserDetailsServiceWrapper.
+ * </p>
+ * <p>
+ * Here is an example configuration of a role hierarchy (hint: read the "&gt;" sign as "includes"):
+<pre>
+        &lt;property name="hierarchy"&gt;
+            &lt;value&gt;
+                ROLE_A &gt; ROLE_B
+                ROLE_B &gt; ROLE_AUTHENTICATED
+                ROLE_AUTHENTICATED &gt; ROLE_UNAUTHENTICATED
+            &lt;/value&gt;
+        &lt;/property&gt;
+</pre>
+</p>
+ * <p>
+ * Explanation of the above:<br>
+ * In effect every user with ROLE_A also has ROLE_B, ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;<br>
+ * every user with ROLE_B also has ROLE_AUTHENTICATED and ROLE_UNAUTHENTICATED;<br>
+ * every user with ROLE_AUTHENTICATED also has ROLE_UNAUTHENTICATED.
+ * </p>
+ * <p>
+ * Hierarchical Roles will dramatically shorten your access rules (and also make the access rules much more elegant).
+ * </p>
+ * <p>
+ * Consider this access rule for Spring Security's RoleVoter (background: every user that is authenticated should be
+ * able to log out):<br>
+ * /logout.html=ROLE_A,ROLE_B,ROLE_AUTHENTICATED<br>
+ * With hierarchical roles this can now be shortened to:<br>
+ * /logout.html=ROLE_AUTHENTICATED<br>
+ * In addition to shorter rules this will also make your access rules more readable and your intentions clearer.
+ * </p>
+ *
+ * @author Michael Mayr
+ *
+ */
+public class RoleHierarchyImpl implements RoleHierarchy {
+
+    private static final Log logger = LogFactory.getLog(RoleHierarchyImpl.class);
+
+    private String roleHierarchyStringRepresentation = null;
+
+    /**
+     * rolesReachableInOneStepMap is a Map that under the key of a specific role name contains a set of all roles
+     * reachable from this role in 1 step
+     */
+    private Map<GrantedAuthority, Set<GrantedAuthority>> rolesReachableInOneStepMap = null;
+
+    /**
+     * rolesReachableInOneOrMoreStepsMap is a Map that under the key of a specific role name contains a set of all
+     * roles reachable from this role in 1 or more steps
+     */
+    private Map<GrantedAuthority, Set<GrantedAuthority>> rolesReachableInOneOrMoreStepsMap = null;
+
+    /**
+     * Set the role hierarchy and pre-calculate for every role the set of all reachable roles, i.e. all roles lower in
+     * the hierarchy of every given role. Pre-calculation is done for performance reasons (reachable roles can then be
+     * calculated in O(1) time).
+     * During pre-calculation, cycles in role hierarchy are detected and will cause a
+     * <tt>CycleInRoleHierarchyException</tt> to be thrown.
+     *
+     * @param roleHierarchyStringRepresentation - String definition of the role hierarchy.
+     */
+    public void setHierarchy(String roleHierarchyStringRepresentation) {
+        this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation;
+
+        logger.debug("setHierarchy() - The following role hierarchy was set: " + roleHierarchyStringRepresentation);
+
+        buildRolesReachableInOneStepMap();
+        buildRolesReachableInOneOrMoreStepsMap();
+    }
+
+    public List<GrantedAuthority> getReachableGrantedAuthorities(List<GrantedAuthority> authorities) {
+        if (authorities == null || authorities.isEmpty()) {
+            return null;
+        }
+
+        Set<GrantedAuthority> reachableRoles = new HashSet<GrantedAuthority>();
+
+        for (GrantedAuthority authority : authorities) {
+            addReachableRoles(reachableRoles, authority);
+            Set<GrantedAuthority> additionalReachableRoles = getRolesReachableInOneOrMoreSteps(authority);
+            if (additionalReachableRoles != null) {
+                reachableRoles.addAll(additionalReachableRoles);
+            }
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("getReachableGrantedAuthorities() - From the roles " + authorities
+                    + " one can reach " + reachableRoles + " in zero or more steps.");
+        }
+
+        List<GrantedAuthority> reachableRoleList = new ArrayList<GrantedAuthority>(reachableRoles.size());
+        reachableRoleList.addAll(reachableRoles);
+
+        return reachableRoleList;
+    }
+
+    // SEC-863
+	private void addReachableRoles(Set<GrantedAuthority> reachableRoles,
+			GrantedAuthority authority) {
+		
+		Iterator<GrantedAuthority> iterator = reachableRoles.iterator();		
+		while (iterator.hasNext()) {
+			GrantedAuthority testAuthority = iterator.next(); 
+			String testKey = testAuthority.getAuthority();
+			if ((testKey != null) && (testKey.equals(authority.getAuthority()))) {
+				return;
+			}
+		}
+		reachableRoles.add(authority);
+	}
+
+    // SEC-863
+	private Set<GrantedAuthority> getRolesReachableInOneOrMoreSteps(
+			GrantedAuthority authority) {
+		
+		if (authority.getAuthority() == null) {
+			return null;
+		}
+		
+		Iterator<GrantedAuthority> iterator = rolesReachableInOneOrMoreStepsMap.keySet().iterator();		
+		while (iterator.hasNext()) {
+			GrantedAuthority testAuthority = iterator.next(); 
+			String testKey = testAuthority.getAuthority();
+			if ((testKey != null) && (testKey.equals(authority.getAuthority()))) {
+				return rolesReachableInOneOrMoreStepsMap.get(testAuthority);
+			}
+		}
+		
+		return null;
+	}
+    
+    /**
+     * Parse input and build the map for the roles reachable in one step: the higher role will become a key that
+     * references a set of the reachable lower roles.
+     */
+    private void buildRolesReachableInOneStepMap() {
+        Pattern pattern = Pattern.compile("(\\s*([^\\s>]+)\\s*\\>\\s*([^\\s>]+))");
+
+        Matcher roleHierarchyMatcher = pattern.matcher(roleHierarchyStringRepresentation);
+        rolesReachableInOneStepMap = new HashMap<GrantedAuthority, Set<GrantedAuthority>>();
+
+        while (roleHierarchyMatcher.find()) {
+            GrantedAuthority higherRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(2));
+            GrantedAuthority lowerRole = new GrantedAuthorityImpl(roleHierarchyMatcher.group(3));
+            Set<GrantedAuthority> rolesReachableInOneStepSet = null;
+
+            if (!rolesReachableInOneStepMap.containsKey(higherRole)) {
+                rolesReachableInOneStepSet = new HashSet<GrantedAuthority>();
+                rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet);
+            } else {
+                rolesReachableInOneStepSet = rolesReachableInOneStepMap.get(higherRole);
+            }
+            addReachableRoles(rolesReachableInOneStepSet, lowerRole);
+
+            logger.debug("buildRolesReachableInOneStepMap() - From role "
+                    + higherRole + " one can reach role " + lowerRole + " in one step.");
+        }
+    }
+
+    /**
+     * For every higher role from rolesReachableInOneStepMap store all roles that are reachable from it in the map of
+     * roles reachable in one or more steps. (Or throw a CycleInRoleHierarchyException if a cycle in the role
+     * hierarchy definition is detected)
+     */
+    private void buildRolesReachableInOneOrMoreStepsMap() {
+        rolesReachableInOneOrMoreStepsMap = new HashMap<GrantedAuthority, Set<GrantedAuthority>>();
+        // iterate over all higher roles from rolesReachableInOneStepMap
+
+        for(GrantedAuthority role : rolesReachableInOneStepMap.keySet()) {
+            Set<GrantedAuthority> rolesToVisitSet = new HashSet<GrantedAuthority>();
+
+            if (rolesReachableInOneStepMap.containsKey(role)) {
+                rolesToVisitSet.addAll(rolesReachableInOneStepMap.get(role));
+            }
+
+            Set<GrantedAuthority> visitedRolesSet = new HashSet<GrantedAuthority>();
+
+            while (!rolesToVisitSet.isEmpty()) {
+                // take a role from the rolesToVisit set
+                GrantedAuthority aRole = (GrantedAuthority) rolesToVisitSet.iterator().next();
+                rolesToVisitSet.remove(aRole);
+                addReachableRoles(visitedRolesSet, aRole);
+                if (rolesReachableInOneStepMap.containsKey(aRole)) {
+                    Set<GrantedAuthority> newReachableRoles = rolesReachableInOneStepMap.get(aRole);
+
+                    // definition of a cycle: you can reach the role you are starting from
+                    if (rolesToVisitSet.contains(role) || visitedRolesSet.contains(role)) {
+                        throw new CycleInRoleHierarchyException();
+                    } else {
+                         // no cycle
+                        rolesToVisitSet.addAll(newReachableRoles);
+                    }
+                }
+            }
+            rolesReachableInOneOrMoreStepsMap.put(role, visitedRolesSet);
+
+            logger.debug("buildRolesReachableInOneOrMoreStepsMap() - From role "
+                    + role + " one can reach " + visitedRolesSet + " in one or more steps.");
+        }
+
+    }
+
+}

+ 92 - 40
core/src/test/java/org/springframework/security/access/hierarchicalroles/HierarchicalRolesTestHelper.java

@@ -1,40 +1,92 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.hierarchicalroles;
-
-import java.util.List;
-
-import org.springframework.security.core.GrantedAuthority;
-import org.apache.commons.collections.CollectionUtils;
-
-/**
- * Test helper class for the hierarchical roles tests.
- *
- * @author Michael Mayr
- */
-public abstract class HierarchicalRolesTestHelper {
-
-    public static boolean containTheSameGrantedAuthorities(List<GrantedAuthority> authorities1, List<GrantedAuthority> authorities2) {
-        if (authorities1 == null && authorities2 == null) {
-            return true;
-        }
-
-        if (authorities1 == null || authorities2 == null) {
-            return false;
-        }
-        return CollectionUtils.isEqualCollection(authorities1, authorities2);
-    }
-
-}
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.access.hierarchicalroles;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.apache.commons.collections.CollectionUtils;
+
+/**
+ * Test helper class for the hierarchical roles tests.
+ *
+ * @author Michael Mayr
+ */
+public abstract class HierarchicalRolesTestHelper {
+
+    public static boolean containTheSameGrantedAuthorities(List<GrantedAuthority> authorities1, List<GrantedAuthority> authorities2) {
+        if (authorities1 == null && authorities2 == null) {
+            return true;
+        }
+
+        if (authorities1 == null || authorities2 == null) {
+            return false;
+        }
+        return CollectionUtils.isEqualCollection(authorities1, authorities2);
+    }
+
+    public static boolean containTheSameGrantedAuthoritiesCompareByAuthorityString(List<GrantedAuthority> authorities1, List<GrantedAuthority> authorities2) {
+        if (authorities1 == null && authorities2 == null) {
+            return true;
+        }
+
+        if (authorities1 == null || authorities2 == null) {
+            return false;
+        }
+        return CollectionUtils.isEqualCollection(toListOfAuthorityStrings(authorities1), toListOfAuthorityStrings(authorities2));
+    }
+
+    public static List<String> toListOfAuthorityStrings(List<GrantedAuthority> authorities) {
+        if (authorities == null) {
+            return null;
+        }
+
+        List<String> result = new ArrayList<String>(authorities.size());
+        for (GrantedAuthority authority : authorities) {
+            result.add(authority.getAuthority());
+        }
+        return result;
+    }
+
+    public static List<GrantedAuthority> createAuthorityList(final String... roles) {
+        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(roles.length);
+
+        for (final String role : roles) {
+            // Use non GrantedAuthorityImpl (SEC-863)
+            authorities.add(new GrantedAuthority() {
+                public String getAuthority() {
+                    return role;
+                }
+
+                public int compareTo(GrantedAuthority ga) {
+                    if (ga != null) {
+                        String rhsRole = ga.getAuthority();
+
+                        if (rhsRole == null) {
+                            return -1;
+                        }
+
+                        return role.compareTo(rhsRole);
+                    }
+                    return -1;
+                }
+            });
+        }
+
+        return authorities;
+    }
+
+}

+ 128 - 114
core/src/test/java/org/springframework/security/access/hierarchicalroles/RoleHierarchyImplTests.java

@@ -1,114 +1,128 @@
-/*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package org.springframework.security.access.hierarchicalroles;
-
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.springframework.security.access.hierarchicalroles.CycleInRoleHierarchyException;
-import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.AuthorityUtils;
-
-/**
- * Tests for {@link RoleHierarchyImpl}.
- *
- * @author Michael Mayr
- */
-public class RoleHierarchyImplTests extends TestCase {
-
-    public void testSimpleRoleHierarchy() {
-
-        List<GrantedAuthority> authorities0 = AuthorityUtils.createAuthorityList("ROLE_0");
-        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A");
-        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B");
-
-        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B");
-
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), authorities0));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), authorities2));
-    }
-
-    public void testTransitiveRoleHierarchies() {
-        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A");
-        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B","ROLE_C");
-        List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B","ROLE_C","ROLE_D");
-
-        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-
-        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C");
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2));
-
-        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_D");
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities3));
-    }
-
-    public void testComplexRoleHierarchy() {
-        List<GrantedAuthority> authoritiesInput1 = AuthorityUtils.createAuthorityList("ROLE_A");
-        List<GrantedAuthority> authoritiesOutput1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B","ROLE_C", "ROLE_D");
-        List<GrantedAuthority> authoritiesInput2 = AuthorityUtils.createAuthorityList("ROLE_B");
-        List<GrantedAuthority> authoritiesOutput2 = AuthorityUtils.createAuthorityList("ROLE_B","ROLE_D");
-        List<GrantedAuthority> authoritiesInput3 = AuthorityUtils.createAuthorityList("ROLE_C");
-        List<GrantedAuthority> authoritiesOutput3 = AuthorityUtils.createAuthorityList("ROLE_C","ROLE_D");
-        List<GrantedAuthority> authoritiesInput4 = AuthorityUtils.createAuthorityList("ROLE_D");
-        List<GrantedAuthority> authoritiesOutput4 = AuthorityUtils.createAuthorityList("ROLE_D");
-
-        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D");
-
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput1), authoritiesOutput1));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput2), authoritiesOutput2));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput3), authoritiesOutput3));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput4), authoritiesOutput4));
-    }
-
-    public void testCyclesInRoleHierarchy() {
-        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-
-        try {
-            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_A");
-            fail("Cycle in role hierarchy was not detected!");
-        } catch (CycleInRoleHierarchyException e) {}
-
-        try {
-            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_A");
-            fail("Cycle in role hierarchy was not detected!");
-        } catch (CycleInRoleHierarchyException e) {}
-
-        try {
-            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_A");
-            fail("Cycle in role hierarchy was not detected!");
-        } catch (CycleInRoleHierarchyException e) {}
-
-        try {
-            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_E\nROLE_E > ROLE_D\nROLE_D > ROLE_B");
-            fail("Cycle in role hierarchy was not detected!");
-        } catch (CycleInRoleHierarchyException e) {}
-    }
-
-    public void testNoCyclesInRoleHierarchy() {
-        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
-
-        try {
-            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D");
-        } catch (CycleInRoleHierarchyException e) {
-            fail("A cycle in role hierarchy was incorrectly detected!");
-        }
-    }
-
-}
+/*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.springframework.security.access.hierarchicalroles;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.security.access.hierarchicalroles.CycleInRoleHierarchyException;
+import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+
+/**
+ * Tests for {@link RoleHierarchyImpl}.
+ *
+ * @author Michael Mayr
+ */
+public class RoleHierarchyImplTests extends TestCase {
+
+    public void testSimpleRoleHierarchy() {
+
+        List<GrantedAuthority> authorities0 = AuthorityUtils.createAuthorityList("ROLE_0");
+        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B");
+
+        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
+        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B");
+
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), authorities0));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), authorities2));
+    }
+
+    public void testTransitiveRoleHierarchies() {
+        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B","ROLE_C");
+        List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B","ROLE_C","ROLE_D");
+
+        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
+
+        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C");
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2));
+
+        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_D");
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities3));
+    }
+
+    public void testComplexRoleHierarchy() {
+        List<GrantedAuthority> authoritiesInput1 = AuthorityUtils.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authoritiesOutput1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B","ROLE_C", "ROLE_D");
+        List<GrantedAuthority> authoritiesInput2 = AuthorityUtils.createAuthorityList("ROLE_B");
+        List<GrantedAuthority> authoritiesOutput2 = AuthorityUtils.createAuthorityList("ROLE_B","ROLE_D");
+        List<GrantedAuthority> authoritiesInput3 = AuthorityUtils.createAuthorityList("ROLE_C");
+        List<GrantedAuthority> authoritiesOutput3 = AuthorityUtils.createAuthorityList("ROLE_C","ROLE_D");
+        List<GrantedAuthority> authoritiesInput4 = AuthorityUtils.createAuthorityList("ROLE_D");
+        List<GrantedAuthority> authoritiesOutput4 = AuthorityUtils.createAuthorityList("ROLE_D");
+
+        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
+        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D");
+
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput1), authoritiesOutput1));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput2), authoritiesOutput2));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput3), authoritiesOutput3));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(roleHierarchyImpl.getReachableGrantedAuthorities(authoritiesInput4), authoritiesOutput4));
+    }
+
+    public void testCyclesInRoleHierarchy() {
+        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
+
+        try {
+            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_A");
+            fail("Cycle in role hierarchy was not detected!");
+        } catch (CycleInRoleHierarchyException e) {}
+
+        try {
+            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_A");
+            fail("Cycle in role hierarchy was not detected!");
+        } catch (CycleInRoleHierarchyException e) {}
+
+        try {
+            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_A");
+            fail("Cycle in role hierarchy was not detected!");
+        } catch (CycleInRoleHierarchyException e) {}
+
+        try {
+            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_B > ROLE_C\nROLE_C > ROLE_E\nROLE_E > ROLE_D\nROLE_D > ROLE_B");
+            fail("Cycle in role hierarchy was not detected!");
+        } catch (CycleInRoleHierarchyException e) {}
+    }
+
+    public void testNoCyclesInRoleHierarchy() {
+        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
+
+        try {
+            roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B\nROLE_A > ROLE_C\nROLE_C > ROLE_D\nROLE_B > ROLE_D");
+        } catch (CycleInRoleHierarchyException e) {
+            fail("A cycle in role hierarchy was incorrectly detected!");
+        }
+    }
+    
+    // SEC-863
+    public void testSimpleRoleHierarchyWithCustomGrantedAuthorityImplementation() {
+
+        List<GrantedAuthority> authorities0 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_0");
+        List<GrantedAuthority> authorities1 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authorities2 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A","ROLE_B");
+
+        RoleHierarchyImpl roleHierarchyImpl = new RoleHierarchyImpl();
+        roleHierarchyImpl.setHierarchy("ROLE_A > ROLE_B");
+
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(roleHierarchyImpl.getReachableGrantedAuthorities(authorities0), authorities0));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(roleHierarchyImpl.getReachableGrantedAuthorities(authorities1), authorities2));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(roleHierarchyImpl.getReachableGrantedAuthorities(authorities2), authorities2));
+    }
+}

+ 143 - 55
core/src/test/java/org/springframework/security/access/hierarchicalroles/TestHelperTests.java

@@ -1,55 +1,143 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.access.hierarchicalroles;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-
-import org.junit.Test;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.AuthorityUtils;
-
-/**
- * Tests for {@link HierarchicalRolesTestHelper}.
- *
- * @author Michael Mayr
- */
-public class TestHelperTests {
-
-    @Test
-    public void testContainTheSameGrantedAuthorities() {
-        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B");
-        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_B","ROLE_A");
-        List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_C");
-        List<GrantedAuthority> authorities4 = AuthorityUtils.createAuthorityList("ROLE_A");
-        List<GrantedAuthority> authorities5 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_A");
-
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, null));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities1));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities2));
-        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities2, authorities1));
-
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, authorities1));
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, null));
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities3));
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities3, authorities1));
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities4));
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities1));
-        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities5));
-    }
-
-}
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.access.hierarchicalroles;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.junit.Test;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+
+/**
+ * Tests for {@link HierarchicalRolesTestHelper}.
+ *
+ * @author Michael Mayr
+ */
+public class TestHelperTests {
+
+    @Test
+    public void testContainTheSameGrantedAuthorities() {
+        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_B");
+        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_B","ROLE_A");
+        List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_C");
+        List<GrantedAuthority> authorities4 = AuthorityUtils.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authorities5 = AuthorityUtils.createAuthorityList("ROLE_A","ROLE_A");
+
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, null));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities1));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities2));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities2, authorities1));
+
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, authorities1));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, null));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities3));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities3, authorities1));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities4));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities1));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities5));
+    }
+
+    // SEC-863
+    @Test
+    public void testToListOfAuthorityStrings() {
+        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B");
+        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_B", "ROLE_A");
+        List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_C");
+        List<GrantedAuthority> authorities4 = AuthorityUtils.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authorities5 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_A");
+
+        List<String> authoritiesStrings1 = new ArrayList<String>();
+        authoritiesStrings1.add("ROLE_A");
+        authoritiesStrings1.add("ROLE_B");
+
+        List<String> authoritiesStrings2 = new ArrayList<String>();
+        authoritiesStrings2.add("ROLE_B");
+        authoritiesStrings2.add("ROLE_A");
+
+        List<String> authoritiesStrings3 = new ArrayList<String>();
+        authoritiesStrings3.add("ROLE_A");
+        authoritiesStrings3.add("ROLE_C");
+
+        List<String> authoritiesStrings4 = new ArrayList<String>();
+        authoritiesStrings4.add("ROLE_A");
+
+        List<String> authoritiesStrings5 = new ArrayList<String>();
+        authoritiesStrings5.add("ROLE_A");
+        authoritiesStrings5.add("ROLE_A");
+
+        assertTrue(CollectionUtils.isEqualCollection(
+                HierarchicalRolesTestHelper.toListOfAuthorityStrings(authorities1),	authoritiesStrings1));
+
+        assertTrue(CollectionUtils.isEqualCollection(
+                HierarchicalRolesTestHelper.toListOfAuthorityStrings(authorities2),	authoritiesStrings2));
+
+        assertTrue(CollectionUtils.isEqualCollection(
+                HierarchicalRolesTestHelper.toListOfAuthorityStrings(authorities3),	authoritiesStrings3));
+
+        assertTrue(CollectionUtils.isEqualCollection(
+                HierarchicalRolesTestHelper.toListOfAuthorityStrings(authorities4),	authoritiesStrings4));
+
+        assertTrue(CollectionUtils.isEqualCollection(
+                HierarchicalRolesTestHelper.toListOfAuthorityStrings(authorities5),	authoritiesStrings5));
+    }
+
+    // SEC-863
+    @Test
+    public void testContainTheSameGrantedAuthoritiesCompareByAuthorityString() {
+        List<GrantedAuthority> authorities1 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B");
+        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_B", "ROLE_A");
+        List<GrantedAuthority> authorities3 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_C");
+        List<GrantedAuthority> authorities4 = AuthorityUtils.createAuthorityList("ROLE_A");
+        List<GrantedAuthority> authorities5 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_A");
+
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, null));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities1));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities2));
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities2, authorities1));
+
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(null, authorities1));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, null));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities3));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities3, authorities1));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities1, authorities4));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities1));
+        assertFalse(HierarchicalRolesTestHelper.containTheSameGrantedAuthorities(authorities4, authorities5));
+    }
+
+    // SEC-863
+    @Test
+    public void testContainTheSameGrantedAuthoritiesCompareByAuthorityStringWithAuthorityLists() {
+        List<GrantedAuthority> authorities1 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A", "ROLE_B");
+        List<GrantedAuthority> authorities2 = AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B");
+        assertTrue(HierarchicalRolesTestHelper.containTheSameGrantedAuthoritiesCompareByAuthorityString(authorities1, authorities2));
+    }
+
+    // SEC-863
+    @Test
+    public void testCreateAuthorityList() {
+        List<GrantedAuthority> authorities1 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A");
+        assertEquals(authorities1.size(), 1);
+        assertEquals("ROLE_A", authorities1.get(0).getAuthority());
+
+        List<GrantedAuthority> authorities2 = HierarchicalRolesTestHelper.createAuthorityList("ROLE_A", "ROLE_C");
+        assertEquals(authorities2.size(), 2);
+        assertEquals("ROLE_A", authorities2.get(0).getAuthority());
+        assertEquals("ROLE_C", authorities2.get(1).getAuthority());
+    }
+}