首页 > 解决方案 > 如何在自定义 AuthenticationFailureHandler 中返回由具体派生 AuthenticationException 类型解析的不同错误消息

问题描述

我正在使用 Spring Security 来构建我的博客应用程序的身份验证/授权。我们决定使用 RESTful api,为了在服务器端处理身份验证错误时向客户端返回 json 消息,我必须编写自定义AuthenticationFailureHandler,例如:

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");
    }
}

有一些具体的AuthenticationException派生类型,描述什么是确切的错误,如 :UsernameNotFoundException,,BadCredentialsException...AuthenticationServiceException

在我看来,我应该为不同的异常类型返回不同的错误消息。例如,对于UsernameNotFoundExceptionBadCredentialsException,我可能会返回“错误的用户名或密码,对于AuthenticationServiceException,我可能会返回“在获取您的凭据期间发生了一些错误,请稍后重试”和不同的 HTTP 状态代码(如 500)。

现在问题来了,我知道我可以编写如下代码:

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

要处理这个问题,但这似乎不是最好的解决方案,我必须编写一系列else if块。

我读过一些类似https://stackoverflow.com/a/46530064/8510613的帖子,似乎使用 @ControllerAdviceHandlerExceptionResolver也不是最好的解决方案。

那么我应该如何处理这个问题呢?

标签: springrestspring-mvcauthenticationspring-security

解决方案


您可以使用DelegatingAuthenticationFailureHandler进一步做出决定

一个 AuthenticationFailureHandler,它根据传递给 onAuthenticationFailure 的 AuthenticationException 类型委托给其他 AuthenticationFailureHandler 实例


推荐阅读