user8510613
user8510613

Reputation: 1282

How to return different error message resolved by concrete derived AuthenticationException type in custom AuthenticationFailureHandler

I am using Spring Security to construct my blog application's authentication/authorization. We've decided to use RESTful api, in order to return json message to the client while handling the authentication error in the server side, i have to write custom AuthenticationFailureHandler, like:

public class RganAuthenticationFailureHandler implements AuthenticationFailureHandler {
    private static Logger logger = LoggerFactory.getLogger(RganAuthenticationFailureHandler.class);


    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        httpServletResponse.getWriter().write("some description");
    }
}

The AuthenticationException have some concrete derived type, describe what's the exact error, like: UsernameNotFoundException, BadCredentialsException, AuthenticationServiceException...

It seems to me that i should return different error message for different exception type. For example, for UsernameNotFoundException and BadCredentialsException, i might return "wrong username or password, for AuthenticationServiceException, i might return "some sth wrong happen during getting your credentials, please retry later" and a different HTTP status code(like 500).

Now here's the problem, i know i can write code like:

if(e instanceof UsernameNotFoundException || e instanceof BadCredentialsException){
    httpServletResponse.getWriter.write("message1");
}else if(e instance of AuthenticationServiceException){
    httpServletResponse.getWriter.write("message2");
}else if(...){
    // ...
}

to handle this, but it seems not to be the best solution, i have to write a serie of else if block.

I've read some post like https://stackoverflow.com/a/46530064/8510613, it seems that use @ControllerAdvice and HandlerExceptionResolver is also not the best solution.

So how should i handle this problem?

Upvotes: 1

Views: 368

Answers (1)

codebrane
codebrane

Reputation: 4620

You could make the decision further up the stack by using DelegatingAuthenticationFailureHandler

An AuthenticationFailureHandler that delegates to other AuthenticationFailureHandler instances based upon the type of AuthenticationException passed into onAuthenticationFailure

Upvotes: 1

Related Questions