From 4a7608b7a9f107b712e683c0646954e9462134f6 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Thu, 17 Feb 2011 17:50:46 +0000 Subject: [PATCH] SEC-1640: Add support for "this" property to MethodSecurityExpressionRoot object, representing the object on which the method is actually being invoked. --- ...efaultMethodSecurityExpressionHandler.java | 1 + .../method/MethodSecurityExpressionRoot.java | 17 +++++++++--- .../MethodSecurityExpressionRootTests.java | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java b/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java index bd78c6d2ef..ce788dc1a5 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java +++ b/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; diff --git a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java b/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java index f8717986b0..d689408a0f 100644 --- a/core/src/main/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRoot.java +++ b/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; + } } diff --git a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java b/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java index a2e93071ba..dc3aff5567 100644 --- a/core/src/test/java/org/springframework/security/access/expression/method/MethodSecurityExpressionRootTests.java +++ b/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)); + } }