소스 검색

SEC-1245: Add role hierarchy support to expression handlers. Done.

Luke Taylor 16 년 전
부모
커밋
1c4a809e09

+ 27 - 8
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java

@@ -1,7 +1,10 @@
 package org.springframework.security.access.expression;
 
+import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
+import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
@@ -18,6 +21,9 @@ import org.springframework.security.core.authority.AuthorityUtils;
 public abstract class SecurityExpressionRoot {
     protected final Authentication authentication;
     private AuthenticationTrustResolver trustResolver;
+    private RoleHierarchy roleHierarchy;
+    private Set<String> roles;
+
     /** Allows "permitAll" expression */
     public final boolean permitAll = true;
 
@@ -32,17 +38,11 @@ public abstract class SecurityExpressionRoot {
     }
 
     public final boolean hasRole(String role) {
-        for (GrantedAuthority authority : authentication.getAuthorities()) {
-            if (role.equals(authority.getAuthority())) {
-                return true;
-            }
-        }
-
-        return false;
+        return getAuthoritySet().contains(role);
     }
 
     public final boolean hasAnyRole(String... roles) {
-        Set<String> roleSet = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
+        Set<String> roleSet = getAuthoritySet();
 
         for (String role : roles) {
             if (roleSet.contains(role)) {
@@ -88,4 +88,23 @@ public abstract class SecurityExpressionRoot {
     public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
         this.trustResolver = trustResolver;
     }
+
+    public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
+        this.roleHierarchy = roleHierarchy;
+    }
+
+    private Set<String> getAuthoritySet() {
+        if (roles == null) {
+            roles = new HashSet<String>();
+            List<GrantedAuthority> userAuthorities = authentication.getAuthorities();
+
+            if (roleHierarchy != null) {
+                userAuthorities = roleHierarchy.getReachableGrantedAuthorities(userAuthorities);
+            }
+
+            roles = AuthorityUtils.authorityListToSet(userAuthorities);
+        }
+
+        return roles;
+    }
 }

+ 6 - 0
core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java

@@ -16,6 +16,7 @@ import org.springframework.expression.ExpressionParser;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.security.access.PermissionEvaluator;
 import org.springframework.security.access.expression.ExpressionUtils;
+import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
 import org.springframework.security.core.Authentication;
@@ -37,6 +38,7 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
     private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
     private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
     private ExpressionParser expressionParser = new SpelExpressionParser();
+    private RoleHierarchy roleHierarchy;
 
     public DefaultMethodSecurityExpressionHandler() {
     }
@@ -50,6 +52,7 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
         MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(auth);
         root.setTrustResolver(trustResolver);
         root.setPermissionEvaluator(permissionEvaluator);
+        root.setRoleHierarchy(roleHierarchy);
         ctx.setRootObject(root);
 
         return ctx;
@@ -141,4 +144,7 @@ public class DefaultMethodSecurityExpressionHandler implements MethodSecurityExp
         ((MethodSecurityExpressionRoot)ctx.getRootObject().getValue()).setReturnObject(returnObject);
     }
 
+    public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
+        this.roleHierarchy = roleHierarchy;
+    }
 }

+ 38 - 0
core/src/test/java/org/springframework/security/access/expression/SecurityExpressionRootTests.java

@@ -0,0 +1,38 @@
+package org.springframework.security.access.expression;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
+import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+
+/**
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 3.0
+ */
+public class SecurityExpressionRootTests {
+
+    @Test
+    public void roleHierarchySupportIsCorrectlyUsedInEvaluatingRoles() throws Exception {
+        SecurityExpressionRoot root =
+            new SecurityExpressionRoot(new TestingAuthenticationToken("joe", "pass", "A", "B")) {};
+
+        root.setRoleHierarchy(new RoleHierarchy() {
+            public List<GrantedAuthority> getReachableGrantedAuthorities(List<GrantedAuthority> authorities) {
+                return AuthorityUtils.createAuthorityList("C");
+            }
+        });
+
+        assertTrue(root.hasRole("C"));
+        assertFalse(root.hasRole("A"));
+        assertFalse(root.hasRole("B"));
+        assertTrue(root.hasAnyRole("C", "A", "B"));
+        assertFalse(root.hasAnyRole("A", "B"));
+    }
+}

+ 7 - 0
web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java

@@ -5,6 +5,7 @@ import org.springframework.expression.ExpressionParser;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
 import org.springframework.security.core.Authentication;
@@ -22,6 +23,7 @@ public class DefaultWebSecurityExpressionHandler implements WebSecurityExpressio
 
     private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
     private ExpressionParser expressionParser = new SpelExpressionParser();
+    private RoleHierarchy roleHierarchy;
 
     public ExpressionParser getExpressionParser() {
         return expressionParser;
@@ -31,8 +33,13 @@ public class DefaultWebSecurityExpressionHandler implements WebSecurityExpressio
         StandardEvaluationContext ctx = new StandardEvaluationContext();
         SecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
         root.setTrustResolver(trustResolver);
+        root.setRoleHierarchy(roleHierarchy);
         ctx.setRootObject(root);
 
         return ctx;
     }
+
+    public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
+        this.roleHierarchy = roleHierarchy;
+    }
 }