We're using Spring Security 3.1.3-RELEASE with method-level security. It works perfectly.
I'd like to log, and maybe show to the user, why he is getting denied access.
Using a org.springframework.security.web.access.AccessDeniedHandlerImpl
subclass, I can get a reference to the org.springframework.security.access.AccessDeniedException
thrown, but I can't find a way to determine what caused it (eg, 'Missing role ROLE_ADMIN' or something to that effect).
Am I missing something, or does it simply not exist?
Unfortunately, it is not possible with default implementations available in Spring Security.
I investigated source code and...
MethodSecurityInterceptor
is responsible for protecting method invocations. It delegates access decisions to AccessDecisionManager
.
I checked every implementation of AccessDecisionManager
available out of box.
Each of them throws AccessDeniedException
exception in similar way.
case AccessDecisionVoter.ACCESS_DENIED:
throw new AccessDeniedException(
messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied")
);
AbstractAccessDecisionManager.accessDenied
is name of the message, which can be localized.
For English it is:
AbstractAccessDecisionManager.accessDenied=Access is denied
There are several languages available out of box, and you can make you own translations, but...
That's all, no more information about reasons of exception.
More information about localization of exception messages:
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#localization
I also created a jira issue for that: https://jira.spring.io/browse/SEC-3104
@PreAuthorize, @PostAuthorize, @Secured
annotation can have a parameter to point custom message property in order to set detailed & more user friendly exception messages.
This could also be done by providing a param. to define an class name that extends AccessDeniedException
to raise to you let users handle the rest.
This way, while processing complex rules like
@PreAuthorize("record.createuser != authentication.getName()")
We can get a defined error like
"You cannot process a record that you created.""
etc. instead of "Access is denied"
I have implemented a solution which works (only) for authorization annotations used in the API layer (e.g. with @RequestMapping). See my answer here: https://stackoverflow.com/a/64846057/4413638
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With