7

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?

Community
  • 1
  • 1
shazinltc
  • 3,616
  • 7
  • 34
  • 49

2 Answers2

11

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.

Shaun the Sheep
  • 22,353
  • 1
  • 72
  • 100
  • Thanks got the point. I would like to do what I do for all other exceptions, ie returning a JSON response. Is there a way to do something like in the AccessDeniedHandler? – shazinltc Jan 20 '13 at 15:09
  • You can write a custom `AuthenticationEntryPoint` and use it in the snippet above. Use `Http403ForbiddenEntryPoint` as a starting point. – Shaun the Sheep Jan 20 '13 at 15:58
  • Got it :) I din't have to write a custom AuthenticationEntryPoint. A simple 403 response was enough. Thanks btw. – shazinltc Jan 21 '13 at 10:05
  • 3
    how you resolve your problem? Could you share your configuration? I have the same problem I cannot catch AccessDeniedException (or even other throws during authorization process) – Roman Dec 16 '13 at 18:11
2

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.

ben75
  • 29,217
  • 10
  • 88
  • 134
  • I think that is invoked when the user is already authenticated and then he is accessing something he is not supposed to. That isn't my case. I have made an update. – shazinltc Jan 20 '13 at 14:04