mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-09-08 20:51:41 +00:00
SEC-1576: Parameterize the secured object type in AccessDecisionVoter.
This commit is contained in:
parent
85d685f7d3
commit
c8820166c8
@ -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",
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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}.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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_";
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
// ========================================================================================================
|
// ========================================================================================================
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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) ?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user