【问题标题】:How to catch correct exceptions thrown from AuthenticationProvider? [duplicate]如何捕获从 AuthenticationProvider 抛出的正确异常? [复制]
【发布时间】:2019-12-28 16:43:38
【问题描述】:

我正在我的应用中实现自定义身份验证提供程序。在我的提供程序中,我会根据情况使用不同的消息抛出不同的异常。请看我的代码:

@Component
public class MyLdapAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        // Connect to LDAP - throw ConnectionException if the LDAP server is unreachable

        // Authenticate

        // Worng username or password, throw BadCredentialsException("Incorrect username or password.")

        // Not enough right to use my app, throw BadCredentialsException("This user is not allowed to use the service.");
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

为了捕捉这些异常,我实现了一个CustomAuthenticationEntryPoint,如下所示:

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

    private final HandlerExceptionResolver resolver;

    @Autowired
    public CustomAuthenticationEntryPoint(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
        this.resolver = resolver;
    }

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) {
        resolver.resolveException(httpServletRequest, httpServletResponse, null, e);
    }
}

如您所见,我解决了异常,以便可以在@RestControllerAdvice 中再次捕获它(我想集中处理异常)。

我的问题是CustomAuthenticationEntryPoint 的commence 方法将所有异常转换为AuthenticationException。无论我在身份验证提供程序中抛出什么异常,我得到的始终是带有固定消息的身份验证异常:

访问此资源需要完全身份验证

总之,我可以捕获从AuthenticationProvider 抛出的异常,但不是正确的。

我的问题:如何捕获AuthenticationProvider 抛出的正确异常?

【问题讨论】:

  • 不,我的问题是:我怎样才能捕获从AuthenticationProvider 抛出的正确异常?如您所见,我无法捕捉到ConnectionException 或BadCredentialsException。
  • 我已经检查过了。他们只想抓住AuthenticationException。对我来说,情况不同。我想捕获特定异常以了解身份验证失败的原因(无法连接到身份验证源、错误的凭据……)。 AuthenticationException 中没有此信息。
  • 在您最后的评论中,您写道您的问题不是关于异常的类型,而是关于捕获异常。因此,我删除了我的最后一条评论。现在又是关于异常的类型。如果您阅读我的最后一条评论,您就会知道您的问题的答案。
  • 您的问题:不,我的问题是:我怎样才能捕获从 AuthenticationProvider 抛出的正确异常?在其他问题中得到解答。
  • 如您所见,我无法捕获 ConnectionException 或 BadCredentialsException。我的评论中回答了这个问题。

标签: java spring-boot exception spring-security


【解决方案1】:

我解决它的方法是在 CorsFilter 之前添加一个新的过滤器:

在我的SecurityConfigurer 课堂上:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .addFilterBefore(new ExceptionFilter(exceptionHandler), CorsFilter.class)
        .....
}

ExceptionFiler类:

public class ExceptionFilter extends OncePerRequestFilter {

private HandlerExceptionResolver resolver;

public ExceptionFilter(HandlerExceptionResolver resolver) {
    this.resolver = resolver;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    try {
        filterChain.doFilter(request, response);
    } catch (Exception ex) {
        LOG.error("An exception has been thrown by one of the filters: ", ex);
                    ResponseEntity<Object> error;
        if (ex instanceof ConnectionException) {
            error = resolver.handleConnectionException(ex);
        } else if (ex instanceof BadCredentialsException) {
            error = resolver.handleBadCredentialsException(ex);
        } else {
            error = resolver.handleGenericException(ex);
        }

        response.setStatus(error.getStatusCode().value());
        response.getWriter().write(error.getBody().toString());
    }
}

}

你可以玩弄 if 语句、catch 子句等,但你已经明白了。

【讨论】:

  • 我的是ResponseEntityExceptionHandler (org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler)。我想只要你将异常传递给处理程序并不重要......诀窍是在过滤器中实际捕获异常,这样你就可以在 catch 子句中用它做任何你想做的事情
  • @BogdanSucaciu 当然,没关系,但它会分散用户对 Spring 的了解。我建议更改您的答案以使代码正常工作,仅使用界面中的方法resolveException。
  • 请问,您为什么选择在CorsFilter 之前添加这个ExceptionFilter?有什么具体原因吗?
  • 我定义了一个自定义 CSRF 过滤器,它会抛出一些自定义异常。所以,我希望我的ExceptionFilter 也能捕获CsrfFilter 抛出的异常。在您的情况下,我想可以将其放在 UsernamePasswordAuthenticationFilter 之前。
  • handleConnectionException 在 spring boot 3.3.5 中不存在
猜你喜欢
  • 2017-10-14
  • 1970-01-01
  • 2011-07-28
  • 2016-08-24
  • 2013-05-07
  • 2011-05-07
  • 1970-01-01
  • 2011-06-27
相关资源
最近更新 更多