【问题标题】:Spring exception handler outside controller控制器外的 Spring 异常处理程序
【发布时间】:2015-07-12 01:22:28
【问题描述】:

@ControllerAdvice 类中,我有一个@ExceptionHandler,这个处理程序可以很好地处理控制器错误,但是如果我有一个过滤器,它们就无法处理异常。我该如何处理这些异常?

过滤器是:-

public class AuthFilter extends UsernamePasswordAuthenticationFilter {

    private LoginDTO loginDTO;

    public AuthFilter() {
        setRequiresAuthenticationRequestMatcher(
                new AntPathRequestMatcher("/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException {

        try {
            loginDTO = new ObjectMapper().readValue(request.getReader(), LoginDTO.class);
        } catch (Exception e) {
            throw new APIException(ExceptionMessages.INVALID_LOGIN_JSON,
                    HttpStatus.BAD_REQUEST);
        }

        return super.attemptAuthentication(request, response);
    }

    ...
}

异常处理程序是(在@ControllerAdvice 中)

    @ExceptionHandler(APIException.class)
    public ResponseEntity<ErrorDTO> handleAPIException(APIException e) {
        return new ResponseEntity<ErrorDTO>(new ErrorDTO(e.getMessage()),
                e.getHttpStatus());
    }

更新

我的要求是为 spring 安全过滤器提供一个全局异常处理程序。有什么办法吗?

【问题讨论】:

  • 这些错误由 Spring Security 处理,而不是由 @ExceptionHandler 处理,因为这些错误仅适用于控制器并在 DispatcherServlet 过滤器中执行,过滤器在过滤器之前执行,所以不可能 @ExceptionHandler (不移动它到另一个过滤器,基本上将 dispatcherservlet 复制到一个过滤器)可以处理这个(也不应该恕我直言)。你也知道你的自定义过滤器有缺陷吗?
  • 那么有没有办法在全球范围内处理 Spring 安全异常?不,不是真的,缺陷是什么?
  • Spring Security 已经处理了这些异常,那有什么问题呢?您有一个过滤器,对于每个请求,您将结果存储在类级别属性中,loginDTO 现在您认为当 10 个请求进入时会发生什么......
  • 我想要一条 JSON 错误消息。对于每个请求,它不会创建一个新实例吗?那么解决办法是什么?
  • 这是问题,因为此实例存储在过滤器的单个实例中,即共享,因此请求 1 覆盖请求 2。如果您想要 JSON 响应,请创建自定义 ExceptionHandlingFilter。但是你的用例是什么,你为什么要这样做?

标签: java spring spring-security


【解决方案1】:

恐怕你不能。以下是(大致)在 Spring MVC Web 应用程序中如何处理请求:

servlet container
    filters before FilterChain.doFilter
        DispatcherServlet  => here is all Spring MVC machinery
    filters after FilterChain.doFilter
servlet container

所有 Spring MVC 机器都在 DispatcherServlet 内部进行管理,包括所有异常处理。

恕我直言,您可以尝试两件事:

  • 用拦截器 (*) 替换过滤器
  • 在抛出异常的那个之前使用另一个过滤器并在那里捕获它(非 Spring MVC 方式,但过滤器在 Spring MVC 之外)

(*) 你仍然不能使用 ExceptionHandler,因为异常会在控制器之外抛出,但是你可以使用 HandlerExceptionResolver。

【讨论】:

  • 我尝试了你建议的两种方式,HandlerExceptionResolver 对我来说不太有效,但是添加一个过滤器就像一个魅力。谢谢。
猜你喜欢
  • 1970-01-01
  • 2021-06-27
  • 2011-02-07
  • 2015-05-07
  • 2017-12-11
  • 1970-01-01
  • 2016-04-08
  • 1970-01-01
  • 2021-04-13
相关资源
最近更新 更多