Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security - why does RoleVoter supports all classes and WebExpressionVoter only supports subclasses of FilterInvocation?

In the supports(Class clazz) method of RoleVoter, it always returns true saying that

This implementation supports any type of class, because it does not query the presented secure object.

What is this "presented secure object". On the other hand, the supports(Class clazz) method of WebExpressionVoter returns true only if clazz is a subtype of FilterInvocation. Is FilterInvocation the "presented secure object" here and why does the voter has to support it ?

If I use @Secured annotations over my methods and configure an access decision manager for global method security that has WebExpressionVoter as one of the voters, it presents an error

AccessDecisionManager does not support secure object class: interface org.aopalliance.intercept.MethodInvocation

This is because all voters of an access decision manager (when configured for method security) must support the above class, and while RoleVoter and others do, WebExpressionVoter needs a subtype of FilterInvocation.

SPEL expressions in @PreAuthorize tag would also need WebExpressionVoter, and again it would be required to support MethodInvocation class, which it doesn't. But it does work. So what am I getting wrong here ?

like image 999
Daud Avatar asked Apr 11 '12 13:04

Daud


1 Answers

The secured object is an abstract representing whatever is secured. It may be a MethodInvocation in case of @Secured, @RolesAllowed, @PreFilter and @PreAuthorize, or a FilterInvocation in case of <intercept-url /> or any other object if required.

The @PreFilter and @PreAuthorize annotations are handled by PreInvocationAuthorizationAdviceVoter. It uses the MethodInvocation to get the annotations and their attributes values, so it has:

public boolean supports(Class<?> clazz) {
    return clazz.isAssignableFrom(MethodInvocation.class);
}

The WebExpressionVoter is web-invocation specific, because it matches the URL to the patterns from <intercept-url />, that's why it has:

public boolean supports(Class<?> clazz) {
    return clazz.isAssignableFrom(FilterInvocation.class);
}

The RoleVoter only uses the Authentication object contents, so it does not depend on the secured object, and that's why it has:

public boolean supports(Class<?> clazz) {
    return true;
}

Note, that You can have a separate AccessDecisionManager for URL level security and method level security. The first will use voters that support FilterInvocation, and the other the ones that support MethodInvocation. Also note that RoleVoter supports both so it can be used in both contexts.

like image 114
Roadrunner Avatar answered Nov 22 '22 15:11

Roadrunner