Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @ExceptionHandler does not catch AccessDeniedException

I have an exception handler set up with the following code

@ExceptionHandler(Throwable.class)
public @ResponseBody CustomResponse handleException(Throwable throwable){
    // handles exception, returns a JSON
}

I am using Spring Security 3.1. When I try to do an operation without authentication, the application throws an AccessDeniedException. It never comes to this method. But works fine with other exceptions. Is it the way it is supposed to work?? Or is there something wrong with my code?

This looks like a solution. But it would be better if I can handle exceptions at a single point.

Here is my configuration file

<global-method-security secured-annotations="enabled" pre-post-annotations="enabled" />
<http auto-config="true" use-expressions="true">
    //intercept urls
    <form-login login-page="/signin" default-target-url="/" always-use-default-target="true"/>
</http>

<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder ref="encoder" />
    </authentication-provider>
</authentication-manager>

<!-- This encoder doesn't require a salt -->
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

UPDATE

Here the user isn't authenticated (ROLE_ANONYMOUS). When I try to access a protected page, it redirects me to the login URL. My problem here is that, I make an AJAX call. So redirecting to a method that returns ModelAndView doesn't work. Is there a work around here?

like image 885
shazinltc Avatar asked Jan 20 '13 11:01

shazinltc


2 Answers

Spring Security's request handling all takes place in the filter chain, before the dispatcher servlet is invoked, so it doesn't know anything about Spring MVC exception handlers and in fact can be used without Spring MVC at all.

What you are seeing is expected behaviour for an unauthenticated user, but you don't want your Ajax calls to be redirected to UI code. It's difficult to say exactly what the best solution is since it's not obvious what you want the behaviour to be for an unauthenticated ajax call. If you want them to simply fail with a 403, for example, then you can separate the ajax api into a separate filter chain. For example, if your ajax calls are to /ajaxapi could add the following chain definition before the existing one:

<http pattern="/ajaxapi/**" create-session="never" use-expressions="true" entry-point-ref="entryPoint">
    <intercept-url pattern="/**" access="isAuthenticated()" />
</http>

<bean entryPoint="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

The ajax calls would all then just get a 403 response until a user authenticated via the browser interface.

like image 147
Shaun the Sheep Avatar answered Nov 15 '22 04:11

Shaun the Sheep


I guess you defined a <access-denied-handler> in your spring security configuration. This handler is catching the AccessDeniedException. That's probably why you don't get it in your generic ExceptionHandler.

There is a default AccessDeniedHandler (comes with the default spring security setup). Please read this for more details.

like image 20
ben75 Avatar answered Nov 15 '22 05:11

ben75