Spring Security's @PreAuthorize on type level can not be overridden on method level
I'm trying to protect a Controller with the @PreAuthorize
annotation at type level and try to override that behavior by annotating some methods with a different 开发者_运维百科@PreAuthorize
. The Problem is however, that Spring is evaluating the method annotation first (grants access) and is then evaluating the class annotation (denies access).
Is there any way to reverse that order? I couldn't figure it out yet.
Edit:
On the method level, I want to grant access to non-registered Users only:
@PreAuthorize("isAnonymous()")
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String renderCreateEntity(ModelMap model) {
return userService.renderCreateEntity(model);
}
The standard for this Controller however, should be to allow fully authenticated users only:
@Controller
@RequestMapping(value = "/user")
@PreAuthorize("isFullyAuthenticated()")
public class UserController { [...] }
When debug-stepping through the app, I see that isAnonymous()
is evaluated first and then isFullyAuthenticated()
thus resulting in an grant of access right and immediately denying access again.
Thanks for all your replys. The answer however, was something totally different :)
I put this here in case anyone else has the same problems.
I registered a custom validator in an @InitBinder
annotated method. This binding method is called AFTER the method call requested on the controller. And since this binding method was not annotated with @PreAuthorize
, the request was denied.
The solution was to annotate the binding method like this:
@InitBinder
@PreAuthorize("permitAll")
public void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
And then, the method calls from my OP evaluated like expected.
The problem is not that you need to change the order of grant and deny. The problem is simple that that method level annotations override the class level annotations.
PrePostAnnotationSecurityMetadataSource
Java Doc:
Annotations may be specified on classes or methods, and method-specific annotations will take precedence.
The concrete implementation of this logic is done in the method findAnnotation
of class PrePostAnnotationSecurityMetadataSource
. (Unfortunately this method is private.)
So you can write your own MethodSecurityMetadataSource
, if you have a look at the code of PrePostAnnotationSecurityMetadataSource
, you will see how easy it is.
But one warning at the end: the end: difficult task is not rewriting the method, the difficult task is to "inject" the new MethodSecurityMetadataSource
into the security system. I belive you can not do it with the spring security namespace configuration, so you need to replace spring security namespace by explicit bean declaration.
精彩评论