问题
In my web application I am using Spring Security and Spring MVC.
I have secured a couple of methods with @Secured
annotation and configured Spring Security in such a way that when one of those methods is accessed without the proper role, the user is taken to the login page. However, I do not want that behaviour when the offending request comes from Ajax, so I implemented the custom @ExceptionHandler
annotated method to determine the request's context.
This is my exception handler:
@ExceptionHandler(AccessDeniedException.class)
public void handleAccessDeniedException(AccessDeniedException ex, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (isAjax(request)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
} else {
throw ex;
}
}
This way I can both handle the exception myself (for example, log an attempt of accessing the @Secured
method) and then let Spring do its part and redirect the user to the login page by rethrowing the AccessDeniedException. Also, when the request comes from Ajax I set the response status to SC_UNAUTHORIZED
and handle the error on the client side.
Now, this seems to be working fine, but I am getting the following ERROR each time I rethrow the exception from the handleAccessDeniedException
method:
ERROR org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: public void app.controller.BaseController.handleAccessDeniedException(org.springframework.security.access.AccessDeniedException,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception
org.springframework.security.access.AccessDeniedException:
at app.controller.BaseController.handleAccessDeniedException(BaseController.java:23)
at app.controller.BaseController$$FastClassByCGLIB$$8f052058.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
(...)
I have not added any exception handling specifics to spring xml configuration files.
I do not see any issues with the app itself, but the error is there and since I am quite new to Spring MVC and Spring Security, I am guessing that I am not doing this properly. Any suggestions? Thanks!
回答1:
Your exception handler isn't supposed to throw another exception. It's supposed to deal with it and send a response. It's a good idea to check the code if you get an error from a class to see how it behaves.
For the non-ajax case, you'd be better to redirect the response to the login page, if that's what you want. Alternatively, you can customize the AuthenticationEntryPoint
used by Spring Security instead and omit AccessDeniedExceptions
from MVC handling. The behaviour would essentially be the same as the defaul LoginUrlAuthenticationEntryPoint
but you would extend it to return a 403 when an ajax request is detected.
来源:https://stackoverflow.com/questions/16071069/propagating-accessdeniedexception-in-spring-security