SEC-1576: Parameterize the secured object type in AccessDecisionVoter.

This commit is contained in:
Luke Taylor 2010-12-16 15:21:22 +00:00
parent 85d685f7d3
commit c8820166c8
13 changed files with 45 additions and 46 deletions

View File

@ -2,6 +2,7 @@
dependencies { dependencies {
compile project(':spring-security-core'), compile project(':spring-security-core'),
'aopalliance:aopalliance:1.0',
"net.sf.ehcache:ehcache:$ehcacheVersion", "net.sf.ehcache:ehcache:$ehcacheVersion",
"org.springframework:spring-aop:$springVersion", "org.springframework:spring-aop:$springVersion",
"org.springframework:spring-context:$springVersion", "org.springframework:spring-context:$springVersion",

View File

@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AuthorizationServiceException; import org.springframework.security.access.AuthorizationServiceException;
@ -148,7 +149,7 @@ public class AclEntryVoter extends AbstractAclVoter {
return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute()); return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute());
} }
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { public int vote(Authentication authentication, MethodInvocation object, Collection<ConfigAttribute> attributes) {
for(ConfigAttribute attr : attributes) { for(ConfigAttribute attr : attributes) {

View File

@ -22,16 +22,14 @@ import org.springframework.security.core.Authentication;
/** /**
* Indicates a class is responsible for voting on authorization decisions. * Indicates a class is responsible for voting on authorization decisions.
*
* <p> * <p>
* The coordination of voting (ie polling <code>AccessDecisionVoter</code>s, * The coordination of voting (ie polling {@code AccessDecisionVoter}s,
* tallying their responses, and making the final authorization decision) is * tallying their responses, and making the final authorization decision) is
* performed by an {@link org.springframework.security.access.AccessDecisionManager}. * performed by an {@link org.springframework.security.access.AccessDecisionManager}.
* </p>
* *
* @author Ben Alex * @author Ben Alex
*/ */
public interface AccessDecisionVoter { public interface AccessDecisionVoter<S> {
//~ Static fields/initializers ===================================================================================== //~ Static fields/initializers =====================================================================================
int ACCESS_GRANTED = 1; int ACCESS_GRANTED = 1;
@ -41,20 +39,20 @@ public interface AccessDecisionVoter {
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
/** /**
* Indicates whether this <code>AccessDecisionVoter</code> is able to vote on the passed * Indicates whether this {@code AccessDecisionVoter} is able to vote on the passed {@code ConfigAttribute}.
* <code>ConfigAttribute</code>.<p>This allows the <code>AbstractSecurityInterceptor</code> to check every * <p>
* configuration attribute can be consumed by the configured <code>AccessDecisionManager</code> and/or * This allows the {@code AbstractSecurityInterceptor} to check every configuration attribute can be consumed by
* <code>RunAsManager</code> and/or <code>AfterInvocationManager</code>.</p> * the configured {@code AccessDecisionManager} and/or {@code RunAsManager} and/or {@code AfterInvocationManager}.
* *
* @param attribute a configuration attribute that has been configured against the * @param attribute a configuration attribute that has been configured against the
* <code>AbstractSecurityInterceptor</code> * {@code AbstractSecurityInterceptor}
* *
* @return true if this <code>AccessDecisionVoter</code> can support the passed configuration attribute * @return true if this {@code AccessDecisionVoter} can support the passed configuration attribute
*/ */
boolean supports(ConfigAttribute attribute); boolean supports(ConfigAttribute attribute);
/** /**
* Indicates whether the <code>AccessDecisionVoter</code> implementation is able to provide access control * Indicates whether the {@code AccessDecisionVoter} implementation is able to provide access control
* votes for the indicated secured object type. * votes for the indicated secured object type.
* *
* @param clazz the class that is being queried * @param clazz the class that is being queried
@ -65,26 +63,27 @@ public interface AccessDecisionVoter {
/** /**
* Indicates whether or not access is granted. * Indicates whether or not access is granted.
* <p>The decision must be affirmative (<code>ACCESS_GRANTED</code>), negative (<code>ACCESS_DENIED</code>) * <p>
* or the <code>AccessDecisionVoter</code> can abstain (<code>ACCESS_ABSTAIN</code>) from voting. * The decision must be affirmative ({@code ACCESS_GRANTED}), negative ({@code ACCESS_DENIED})
* or the {@code AccessDecisionVoter} can abstain ({@code ACCESS_ABSTAIN}) from voting.
* Under no circumstances should implementing classes return any other value. If a weighting of results is desired, * Under no circumstances should implementing classes return any other value. If a weighting of results is desired,
* this should be handled in a custom {@link org.springframework.security.access.AccessDecisionManager} instead. * this should be handled in a custom {@link org.springframework.security.access.AccessDecisionManager} instead.
* </p> * <p>
* <p>Unless an <code>AccessDecisionVoter</code> is specifically intended to vote on an access control * Unless an {@code AccessDecisionVoter} is specifically intended to vote on an access control
* decision due to a passed method invocation or configuration attribute parameter, it must return * decision due to a passed method invocation or configuration attribute parameter, it must return
* <code>ACCESS_ABSTAIN</code>. This prevents the coordinating <code>AccessDecisionManager</code> from counting * {@code ACCESS_ABSTAIN}. This prevents the coordinating {@code AccessDecisionManager} from counting
* votes from those <code>AccessDecisionVoter</code>s without a legitimate interest in the access control * votes from those {@code AccessDecisionVoter}s without a legitimate interest in the access control
* decision. * decision.
* </p> * <p>
* <p>Whilst the method invocation is passed as a parameter to maximise flexibility in making access * Whilst the secured object (such as a {@code MethodInvocation}) is passed as a parameter to maximise flexibility
* control decisions, implementing classes must never modify the behaviour of the method invocation (such as * in making access control decisions, implementing classes should not modify it or cause the represented invocation
* calling <Code>MethodInvocation.proceed()</code>).</p> * to take place (for example, by calling {@code MethodInvocation.proceed()}).
* *
* @param authentication the caller invoking the method * @param authentication the caller making the invocation
* @param object the secured object * @param object the secured object being invoked
* @param attributes the configuration attributes associated with the method being invoked * @param attributes the configuration attributes associated with the secured object
* *
* @return either {@link #ACCESS_GRANTED}, {@link #ACCESS_ABSTAIN} or {@link #ACCESS_DENIED} * @return either {@link #ACCESS_GRANTED}, {@link #ACCESS_ABSTAIN} or {@link #ACCESS_DENIED}
*/ */
int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes); int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
} }

View File

@ -13,7 +13,7 @@ import org.springframework.security.core.GrantedAuthority;
* @author Ryan Heaton * @author Ryan Heaton
* @since 2.0 * @since 2.0
*/ */
public class Jsr250Voter implements AccessDecisionVoter { public class Jsr250Voter implements AccessDecisionVoter<Object> {
/** /**
* The specified config attribute is supported if its an instance of a {@link Jsr250SecurityConfig}. * The specified config attribute is supported if its an instance of a {@link Jsr250SecurityConfig}.

View File

@ -21,7 +21,7 @@ import org.springframework.security.core.Authentication;
* @author Luke Taylor * @author Luke Taylor
* @since 3.0 * @since 3.0
*/ */
public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter { public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVoter<MethodInvocation> {
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private final PreInvocationAuthorizationAdvice preAdvice; private final PreInvocationAuthorizationAdvice preAdvice;
@ -38,7 +38,7 @@ public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVote
return clazz.isAssignableFrom(MethodInvocation.class); return clazz.isAssignableFrom(MethodInvocation.class);
} }
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { public int vote(Authentication authentication, MethodInvocation method, Collection<ConfigAttribute> attributes) {
// Find prefilter and preauth (or combined) attributes // Find prefilter and preauth (or combined) attributes
// if both null, abstain // if both null, abstain
@ -51,7 +51,7 @@ public class PreInvocationAuthorizationAdviceVoter implements AccessDecisionVote
return ACCESS_ABSTAIN; return ACCESS_ABSTAIN;
} }
boolean allowed = preAdvice.before(authentication, (MethodInvocation)object, preAttr); boolean allowed = preAdvice.before(authentication, method, preAttr);
return allowed ? ACCESS_GRANTED : ACCESS_DENIED; return allowed ? ACCESS_GRANTED : ACCESS_DENIED;
} }

View File

@ -26,18 +26,17 @@ import org.springframework.util.Assert;
* *
* @author Ben Alex * @author Ben Alex
*/ */
public abstract class AbstractAclVoter implements AccessDecisionVoter { public abstract class AbstractAclVoter implements AccessDecisionVoter<MethodInvocation> {
//~ Instance fields ================================================================================================ //~ Instance fields ================================================================================================
private Class<?> processDomainObjectClass; private Class<?> processDomainObjectClass;
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
protected Object getDomainObjectInstance(Object secureObject) { protected Object getDomainObjectInstance(MethodInvocation invocation) {
Object[] args; Object[] args;
Class<?>[] params; Class<?>[] params;
MethodInvocation invocation = (MethodInvocation) secureObject;
params = invocation.getMethod().getParameterTypes(); params = invocation.getMethod().getParameterTypes();
args = invocation.getArguments(); args = invocation.getArguments();
@ -47,7 +46,7 @@ public abstract class AbstractAclVoter implements AccessDecisionVoter {
} }
} }
throw new AuthorizationServiceException("Secure object: " + secureObject throw new AuthorizationServiceException("MethodInvocation: " + invocation
+ " did not provide any argument of type: " + processDomainObjectClass); + " did not provide any argument of type: " + processDomainObjectClass);
} }

View File

@ -41,7 +41,7 @@ import org.springframework.util.Assert;
* *
* @author Ben Alex * @author Ben Alex
*/ */
public class AuthenticatedVoter implements AccessDecisionVoter { public class AuthenticatedVoter implements AccessDecisionVoter<Object> {
//~ Static fields/initializers ===================================================================================== //~ Static fields/initializers =====================================================================================
public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY"; public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
@ -77,9 +77,9 @@ public class AuthenticatedVoter implements AccessDecisionVoter {
/** /**
* This implementation supports any type of class, because it does not query the presented secure object. * This implementation supports any type of class, because it does not query the presented secure object.
* *
* @param clazz the secure object * @param clazz the secure object type
* *
* @return always <code>true</code> * @return always {@code true}
*/ */
public boolean supports(Class<?> clazz) { public boolean supports(Class<?> clazz) {
return true; return true;

View File

@ -49,7 +49,7 @@ import org.springframework.security.core.GrantedAuthority;
* @author Ben Alex * @author Ben Alex
* @author colin sampaleanu * @author colin sampaleanu
*/ */
public class RoleVoter implements AccessDecisionVoter { public class RoleVoter implements AccessDecisionVoter<Object> {
//~ Instance fields ================================================================================================ //~ Instance fields ================================================================================================
private String rolePrefix = "ROLE_"; private String rolePrefix = "ROLE_";

View File

@ -150,7 +150,7 @@ public class AbstractAccessDecisionManagerTests extends TestCase {
} }
} }
private class MockStringOnlyVoter implements AccessDecisionVoter { private class MockStringOnlyVoter implements AccessDecisionVoter<Object> {
public boolean supports(Class<?> clazz) { public boolean supports(Class<?> clazz) {
return String.class.isAssignableFrom(clazz); return String.class.isAssignableFrom(clazz);
} }

View File

@ -19,7 +19,7 @@ public class AbstractAclVoterTests {
public boolean supports(ConfigAttribute attribute) { public boolean supports(ConfigAttribute attribute) {
return false; return false;
} }
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { public int vote(Authentication authentication, MethodInvocation object, Collection<ConfigAttribute> attributes) {
return 0; return 0;
} }
}; };

View File

@ -32,7 +32,7 @@ import java.util.Iterator;
* *
* @author Ben Alex * @author Ben Alex
*/ */
public class DenyAgainVoter implements AccessDecisionVoter { public class DenyAgainVoter implements AccessDecisionVoter<Object> {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================

View File

@ -30,7 +30,7 @@ import java.util.Iterator;
* *
* @author Ben Alex * @author Ben Alex
*/ */
public class DenyVoter implements AccessDecisionVoter { public class DenyVoter implements AccessDecisionVoter<Object> {
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
public boolean supports(ConfigAttribute attribute) { public boolean supports(ConfigAttribute attribute) {

View File

@ -15,12 +15,12 @@ import org.springframework.security.web.FilterInvocation;
* @author Luke Taylor * @author Luke Taylor
* @since 3.0 * @since 3.0
*/ */
public class WebExpressionVoter implements AccessDecisionVoter { public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation> {
private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler(); private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { public int vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes) {
assert authentication != null; assert authentication != null;
assert object != null; assert fi != null;
assert attributes != null; assert attributes != null;
WebExpressionConfigAttribute weca = findConfigAttribute(attributes); WebExpressionConfigAttribute weca = findConfigAttribute(attributes);
@ -29,7 +29,6 @@ public class WebExpressionVoter implements AccessDecisionVoter {
return ACCESS_ABSTAIN; return ACCESS_ABSTAIN;
} }
FilterInvocation fi = (FilterInvocation)object;
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, fi); EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, fi);
return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ? return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ?