SEC-1023: Added support for hasPermission() based on Id and type
This commit is contained in:
+10
@@ -1,5 +1,7 @@
|
||||
package org.springframework.security.expression;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
/**
|
||||
@@ -19,4 +21,12 @@ public class DenyAllPermissionEvaluator implements PermissionEvaluator {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false always
|
||||
*/
|
||||
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
|
||||
Object permission) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.springframework.security.expression;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
|
||||
/**
|
||||
@@ -22,4 +24,16 @@ public interface PermissionEvaluator {
|
||||
* @return true if the permission is granted, false otherwise
|
||||
*/
|
||||
boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission);
|
||||
|
||||
/**
|
||||
* Alternative method for evaluating a permission where only the identifier of the target object
|
||||
* is available, rather than the target instance itself.
|
||||
*
|
||||
* @param authentication represents the user in question. Should not be null.
|
||||
* @param targetId the identifier for the object instance (usually a Long)
|
||||
* @param targetType a String representing the target's type (usually a Java classname). Not null.
|
||||
* @param permission a representation of the permission object as supplied by the expression system. Not null.
|
||||
* @return true if the permission is granted, false otherwise
|
||||
*/
|
||||
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.springframework.security.expression;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.security.Authentication;
|
||||
@@ -7,6 +8,7 @@ import org.springframework.security.AuthenticationTrustResolver;
|
||||
import org.springframework.security.GrantedAuthority;
|
||||
import org.springframework.security.util.AuthorityUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Default root object for use in Spring Security expression evaluations.
|
||||
*
|
||||
@@ -87,6 +89,10 @@ public class SecurityExpressionRoot {
|
||||
return permissionEvaluator.hasPermission(authentication, target, permission);
|
||||
}
|
||||
|
||||
public boolean hasPermission(Object targetId, String targetType, Object permission) {
|
||||
return permissionEvaluator.hasPermission(authentication, (Serializable)targetId, targetType, permission);
|
||||
}
|
||||
|
||||
public Authentication getAuthentication() {
|
||||
return authentication;
|
||||
}
|
||||
|
||||
+64
-12
@@ -2,14 +2,16 @@ package org.springframework.security.expression;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationTrustResolver;
|
||||
import org.springframework.security.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
@@ -20,15 +22,21 @@ import org.springframework.security.providers.UsernamePasswordAuthenticationToke
|
||||
*/
|
||||
public class SecurityExpressionRootTests {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
UsernamePasswordAuthenticationToken joe = new UsernamePasswordAuthenticationToken("joe", "password");
|
||||
SecurityExpressionRoot root;
|
||||
StandardEvaluationContext ctx;
|
||||
Mockery jmock = new Mockery();
|
||||
private AuthenticationTrustResolver trustResolver;
|
||||
private Authentication user;
|
||||
|
||||
|
||||
@Before
|
||||
public void createContext() {
|
||||
root = new SecurityExpressionRoot(joe);
|
||||
user = jmock.mock(Authentication.class);
|
||||
root = new SecurityExpressionRoot(user);
|
||||
ctx = new StandardEvaluationContext();
|
||||
ctx.setRootObject(root);
|
||||
trustResolver = jmock.mock(AuthenticationTrustResolver.class);
|
||||
root.setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -40,24 +48,68 @@ public class SecurityExpressionRootTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasPermissionWorksWithIntegerExpressions() throws Exception {
|
||||
public void isAnonymousReturnsTrueIfTrustResolverReportsAnonymous() {
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(trustResolver).isAnonymous(user); will(returnValue(true));
|
||||
}});
|
||||
assertTrue(root.isAnonymous());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAnonymousReturnsFalseIfTrustResolverReportsNonAnonymous() {
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(trustResolver).isAnonymous(user); will(returnValue(false));
|
||||
}});
|
||||
assertFalse(root.isAnonymous());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasPermissionOnDomainObjectReturnsFalseIfPermissionEvaluatorDoes() throws Exception {
|
||||
final Object dummyDomainObject = new Object();
|
||||
final PermissionEvaluator pe = jmock.mock(PermissionEvaluator.class);
|
||||
ctx.setVariable("domainObject", dummyDomainObject);
|
||||
root.setPermissionEvaluator(pe);
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(pe).hasPermission(user, dummyDomainObject, "ignored"); will(returnValue(false));
|
||||
}});
|
||||
|
||||
assertFalse(root.hasPermission(dummyDomainObject, "ignored"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasPermissionOnDomainObjectReturnsTrueIfPermissionEvaluatorDoes() throws Exception {
|
||||
final Object dummyDomainObject = new Object();
|
||||
final PermissionEvaluator pe = jmock.mock(PermissionEvaluator.class);
|
||||
ctx.setVariable("domainObject", dummyDomainObject);
|
||||
root.setPermissionEvaluator(pe);
|
||||
jmock.checking(new Expectations() {{
|
||||
oneOf(pe).hasPermission(user, dummyDomainObject, "ignored"); will(returnValue(true));
|
||||
}});
|
||||
|
||||
assertTrue(root.hasPermission(dummyDomainObject, "ignored"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void hasPermissionOnDomainObjectWorksWithIntegerExpressions() throws Exception {
|
||||
final Object dummyDomainObject = new Object();
|
||||
ctx.setVariable("domainObject", dummyDomainObject);
|
||||
final PermissionEvaluator pe = jmock.mock(PermissionEvaluator.class);
|
||||
root.setPermissionEvaluator(pe);
|
||||
|
||||
root.setPermissionEvaluator(new PermissionEvaluator () {
|
||||
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
|
||||
// Check the correct target object is passed in
|
||||
assertEquals(dummyDomainObject, targetDomainObject);
|
||||
|
||||
return permission instanceof Integer && ((Integer)permission).intValue() == 10;
|
||||
}
|
||||
});
|
||||
jmock.checking(new Expectations() {{
|
||||
exactly(3).of(pe).hasPermission(with(user), with(dummyDomainObject), with(any(Integer.class)));
|
||||
will(onConsecutiveCalls(returnValue(true), returnValue(true), returnValue(false)));
|
||||
}});
|
||||
|
||||
Expression e = parser.parseExpression("hasPermission(#domainObject, 0xA)");
|
||||
// evaluator returns true
|
||||
assertTrue(ExpressionUtils.evaluateAsBoolean(e, ctx));
|
||||
e = parser.parseExpression("hasPermission(#domainObject, 10)");
|
||||
// evaluator returns true
|
||||
assertTrue(ExpressionUtils.evaluateAsBoolean(e, ctx));
|
||||
e = parser.parseExpression("hasPermission(#domainObject, 0xFF)");
|
||||
// evaluator returns false, make sure return value matches
|
||||
assertFalse(ExpressionUtils.evaluateAsBoolean(e, ctx));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user