Răsfoiți Sursa

SEC-1887: Improve extensibility of expression-based security classes

Introduces a new SecurityExpressionOperations interface which is
implemented by SecurityExpressionRoot
Andrei Stefan 13 ani în urmă
părinte
comite
0f9ee81df1

+ 7 - 9
core/src/main/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandler.java

@@ -10,8 +10,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.security.access.PermissionEvaluator;
 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,7 +20,6 @@ import org.springframework.security.core.Authentication;
  * @since 3.1
  */
 public abstract class AbstractSecurityExpressionHandler<T> implements SecurityExpressionHandler<T>, ApplicationContextAware {
-    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
     private final ExpressionParser expressionParser = new SpelExpressionParser();
     private BeanResolver br;
     private RoleHierarchy roleHierarchy;
@@ -34,17 +31,14 @@ public abstract class AbstractSecurityExpressionHandler<T> implements SecurityEx
 
     /**
      * Invokes the internal template methods to create {@code StandardEvaluationContext} and {@code SecurityExpressionRoot}
-     * objects. The root object will be injected with references to the application context, the {@code roleHierarchy}
-     * if set, and an {@code AuthenticationTrustResolver}.
+     * objects.
      *
      * @param authentication the current authentication object
      * @param invocation the invocation (filter, method, channel)
      * @return the context object for use in evaluating the expression, populated with a suitable root object.
      */
     public final EvaluationContext createEvaluationContext(Authentication authentication, T invocation) {
-        SecurityExpressionRoot root = createSecurityExpressionRoot(authentication, invocation);
-        root.setTrustResolver(trustResolver);
-        root.setRoleHierarchy(roleHierarchy);
+        SecurityExpressionOperations root = createSecurityExpressionRoot(authentication, invocation);
         StandardEvaluationContext ctx = createEvaluationContextInternal(authentication, invocation);
         ctx.setBeanResolver(br);
         ctx.setRootObject(root);
@@ -73,8 +67,12 @@ public abstract class AbstractSecurityExpressionHandler<T> implements SecurityEx
      * @param invocation the invocation (filter, method, channel)
      * @return the object wh
      */
-    protected abstract SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, T invocation);
+    protected abstract SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, T invocation);
 
+    protected RoleHierarchy getRoleHierarchy() {
+		return roleHierarchy;
+	}
+    
     public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
         this.roleHierarchy = roleHierarchy;
     }

+ 30 - 0
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionOperations.java

@@ -0,0 +1,30 @@
+package org.springframework.security.access.expression;
+
+public interface SecurityExpressionOperations {
+
+	public abstract boolean hasAuthority(String authority);
+
+	public abstract boolean hasAnyAuthority(String... authorities);
+
+	public abstract boolean hasRole(String role);
+
+	public abstract boolean hasAnyRole(String... roles);
+
+	public abstract boolean permitAll();
+
+	public abstract boolean denyAll();
+
+	public abstract boolean isAnonymous();
+
+	public abstract boolean isAuthenticated();
+
+	public abstract boolean isRememberMe();
+
+	public abstract boolean isFullyAuthenticated();
+
+	public abstract boolean hasPermission(Object target, Object permission);
+
+	public abstract boolean hasPermission(Object targetId, String targetType,
+			Object permission);
+
+}

+ 61 - 13
core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java

@@ -20,7 +20,7 @@ import org.springframework.security.core.authority.AuthorityUtils;
  * @author Luke Taylor
  * @since 3.0
  */
-public abstract class SecurityExpressionRoot {
+public abstract class SecurityExpressionRoot implements SecurityExpressionOperations {
     protected final Authentication authentication;
     private AuthenticationTrustResolver trustResolver;
     private RoleHierarchy roleHierarchy;
@@ -45,19 +45,35 @@ public abstract class SecurityExpressionRoot {
         this.authentication = a;
     }
 
-    public final boolean hasAuthority(String authority) {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#hasAuthority(java.lang.String)
+	 */
+    @Override
+	public final boolean hasAuthority(String authority) {
         return hasRole(authority);
     }
 
-    public final boolean hasAnyAuthority(String... authorities) {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#hasAnyAuthority(java.lang.String)
+	 */
+    @Override
+	public final boolean hasAnyAuthority(String... authorities) {
         return hasAnyRole(authorities);
     }
 
-    public final boolean hasRole(String role) {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#hasRole(java.lang.String)
+	 */
+    @Override
+	public final boolean hasRole(String role) {
         return getAuthoritySet().contains(role);
     }
 
-    public final boolean hasAnyRole(String... roles) {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#hasAnyRole(java.lang.String)
+	 */
+    @Override
+	public final boolean hasAnyRole(String... roles) {
         Set<String> roleSet = getAuthoritySet();
 
         for (String role : roles) {
@@ -73,27 +89,51 @@ public abstract class SecurityExpressionRoot {
         return authentication;
     }
 
-    public final boolean permitAll() {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#permitAll()
+	 */
+    @Override
+	public final boolean permitAll() {
         return true;
     }
 
-    public final boolean denyAll() {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#denyAll()
+	 */
+    @Override
+	public final boolean denyAll() {
         return false;
     }
 
-    public final boolean isAnonymous() {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#isAnonymous()
+	 */
+    @Override
+	public final boolean isAnonymous() {
         return trustResolver.isAnonymous(authentication);
     }
 
-    public final boolean isAuthenticated() {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#isAuthenticated()
+	 */
+    @Override
+	public final boolean isAuthenticated() {
         return !isAnonymous();
     }
 
-    public final boolean isRememberMe() {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#isRememberMe()
+	 */
+    @Override
+	public final boolean isRememberMe() {
         return trustResolver.isRememberMe(authentication);
     }
 
-    public final boolean isFullyAuthenticated() {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#isFullyAuthenticated()
+	 */
+    @Override
+	public final boolean isFullyAuthenticated() {
         return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication);
     }
 
@@ -124,11 +164,19 @@ public abstract class SecurityExpressionRoot {
         return roles;
     }
 
-    public boolean hasPermission(Object target, Object permission) {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#hasPermission(java.lang.Object, java.lang.Object)
+	 */
+    @Override
+	public boolean hasPermission(Object target, Object permission) {
         return permissionEvaluator.hasPermission(authentication, target, permission);
     }
 
-    public boolean hasPermission(Object targetId, String targetType, Object permission) {
+    /* (non-Javadoc)
+	 * @see org.springframework.security.access.expression.SecurityExpressionOperations#hasPermission(java.lang.Object, java.lang.String, java.lang.Object)
+	 */
+    @Override
+	public boolean hasPermission(Object targetId, String targetType, Object permission) {
         return permissionEvaluator.hasPermission(authentication, (Serializable)targetId, targetType, permission);
     }
 

+ 11 - 5
core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java

@@ -1,7 +1,10 @@
 package org.springframework.security.access.expression.method;
 
 import java.lang.reflect.Array;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
 
 import org.aopalliance.intercept.MethodInvocation;
 import org.apache.commons.logging.Log;
@@ -12,11 +15,11 @@ import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.Expression;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.security.access.PermissionCacheOptimizer;
-import org.springframework.security.access.PermissionEvaluator;
 import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
-import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
 import org.springframework.security.access.expression.ExpressionUtils;
-import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.access.expression.SecurityExpressionOperations;
+import org.springframework.security.authentication.AuthenticationTrustResolver;
+import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
 import org.springframework.security.core.Authentication;
 
 /**
@@ -31,6 +34,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
 
     protected final Log logger = LogFactory.getLog(getClass());
 
+    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
     private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
     private PermissionCacheOptimizer permissionCacheOptimizer = null;
 
@@ -45,10 +49,12 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
     }
 
     @Override
-    protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
+    protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
         MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
         root.setThis(invocation.getThis());
         root.setPermissionEvaluator(getPermissionEvaluator());
+        root.setTrustResolver(trustResolver);
+        root.setRoleHierarchy(getRoleHierarchy());
 
         return root;
     }

+ 1 - 1
core/src/test/java/org/springframework/security/access/expression/AbstractSecurityExpressionHandlerTests.java

@@ -23,7 +23,7 @@ public class AbstractSecurityExpressionHandlerTests {
     public void setUp() throws Exception {
         handler = new AbstractSecurityExpressionHandler<Object>() {
             @Override
-            protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, Object o) {
+            protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, Object o) {
                 return new SecurityExpressionRoot(authentication) {};
             }
         };

+ 8 - 2
web/src/main/java/org/springframework/security/web/access/expression/DefaultWebSecurityExpressionHandler.java

@@ -1,7 +1,9 @@
 package org.springframework.security.web.access.expression;
 
 import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
-import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.access.expression.SecurityExpressionOperations;
+import org.springframework.security.authentication.AuthenticationTrustResolver;
+import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.web.FilterInvocation;
 
@@ -11,11 +13,15 @@ import org.springframework.security.web.FilterInvocation;
  * @since 3.0
  */
 public class DefaultWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler<FilterInvocation> {
+	
+	private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
 
     @Override
-    protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
+    protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
         WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
         root.setPermissionEvaluator(getPermissionEvaluator());
+        root.setTrustResolver(trustResolver);
+        root.setRoleHierarchy(getRoleHierarchy());
         return root;
     }
 }