Browse Source

SEC-1640: Add support for "this" property to MethodSecurityExpressionRoot object, representing the object on which the method is actually being invoked.

Luke Taylor 14 years ago
parent
commit
4a7608b7a9

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

@@ -47,6 +47,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
     @Override
     protected SecurityExpressionRoot createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
         MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
+        root.setThis(invocation.getThis());
         root.setPermissionEvaluator(permissionEvaluator);
 
         return root;

+ 14 - 3
core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java

@@ -1,8 +1,5 @@
 package org.springframework.security.access.expression.method;
 
-import java.io.Serializable;
-
-import org.springframework.security.access.PermissionEvaluator;
 import org.springframework.security.access.expression.SecurityExpressionRoot;
 import org.springframework.security.core.Authentication;
 
@@ -16,6 +13,7 @@ import org.springframework.security.core.Authentication;
 class MethodSecurityExpressionRoot extends SecurityExpressionRoot {
     private Object filterObject;
     private Object returnObject;
+    private Object target;
 
     MethodSecurityExpressionRoot(Authentication a) {
         super(a);
@@ -37,4 +35,17 @@ class MethodSecurityExpressionRoot extends SecurityExpressionRoot {
         return returnObject;
     }
 
+    /**
+     * Sets the "this" property for use in expressions. Typically this will be the "this" property of
+     * the {@code JoinPoint} representing the method invocation which is being protected.
+     *
+     * @param target the target object on which the method in is being invoked.
+     */
+    void setThis(Object target) {
+        this.target = target;
+    }
+
+    public Object getThis() {
+        return target;
+    }
 }

+ 26 - 0
core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java

@@ -15,6 +15,8 @@ import org.springframework.security.access.expression.ExpressionUtils;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.core.Authentication;
 
+import java.util.*;
+
 /**
  * Tests for {@link MethodSecurityExpressionRoot}
  *
@@ -102,4 +104,28 @@ public class MethodSecurityExpressionRootTests {
      // evaluator returns false, make sure return value matches
         assertFalse(ExpressionUtils.evaluateAsBoolean(e, ctx));
     }
+
+    @Test
+    public void hasPermissionWorksWithThisObject() throws Exception {
+        Object targetObject = new Object() {
+            public String getX() {
+                return "x";
+            }
+        };
+        root.setThis(targetObject);
+        Integer i = 2;
+        PermissionEvaluator pe = mock(PermissionEvaluator.class);
+        root.setPermissionEvaluator(pe);
+        when(pe.hasPermission(user, targetObject, i)).thenReturn(true)
+                .thenReturn(false);
+        when(pe.hasPermission(user, "x", i)).thenReturn(true);
+
+        Expression e = parser.parseExpression("hasPermission(this, 2)");
+        assertTrue(ExpressionUtils.evaluateAsBoolean(e, ctx));
+        e = parser.parseExpression("hasPermission(this, 2)");
+        assertFalse(ExpressionUtils.evaluateAsBoolean(e, ctx));
+
+        e = parser.parseExpression("hasPermission(this.x, 2)");
+        assertTrue(ExpressionUtils.evaluateAsBoolean(e, ctx));
+    }
 }