首页 > 解决方案 > 如何在 Spring Security 中为过滤器创建自定义全局异常处理程序?

问题描述

有没有办法自定义处理程序来处理 Spring Security 异常和 Spring Security 过滤器中的自定义异常?我需要一个带有错误信息的格式化响应发送到前端。

标签: javaspring-bootexceptionspring-security

解决方案


您可以通过添加过滤器来实现自定义全局异常处理程序:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionFilter extends OncePerRequestFilter {

    private final ObjectMapper mapper = new ObjectMapper();

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
        HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    try {
        filterChain.doFilter(request, response);
    } catch (Exception ex) {
        mapper.writeValue(response.getWriter(), new ErrorInfo("something bad happened"));
        response.setContentType(MediaType.APPLICATION_JSON);
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.getWriter().close();
        response.getWriter().flush();
    }  
}

发送到前端的错误信息将包含在ErrorInfo类中:

public class ErrorInfo {

    // some custom fields as you wish

    public ErrorInfo(String error) {
        ...
    }
}

正如您在上面看到的,通过添加带有HIGHEST_PRECEDENCE作为值的@Order注释,让过滤器在所有其他过滤器之前执行非常重要。如果还有其他一些具有相同顺序的过滤器,则必须增加它们的顺序(例如,通过将Ordered.HIGHEST_PRECEDENCE替换为Ordered.HIGHEST_PRECEDENCE + 1)以使它们在我们的异常处理过滤器之后执行。

此外,您必须确保您的过滤器在 Spring Security 过滤器链之前执行。因此,您需要通过将application.properties中的security.filter-order属性设置为高于 GlobalExceptionFilter 顺序的某个值来更改 Spring Security 过滤器链的顺序:

security.filter-order=0

当我们的过滤器链中的某个地方发生异常时,异常将被GlobalExceptionFilter捕获,然后创建一个包含错误信息的ErrorInfo对象,并使用Jackson ObjectMapper对其进行序列化。最后,响应以给定的HTTP 状态发送到客户端。


推荐阅读