如何为Spring Security的过滤器创建自定义全局异常处理程序?

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

也许你可以看看这个链接,它可能会有所帮助:https://www.devglan.com/spring-security/exception-handling-in-spring-security - Avi
@Avi 谢谢,它只告诉了 Spring Security 的异常,而不是自定义的异常。 - wl.GIG
1个回答

4
你可以通过添加一个过滤器来实现自定义全局异常处理程序:
@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) {
        ...
    }
}

如上所示,为了让过滤器在其他所有过滤器之前执行,需要使用@Order注释,并将值设置为HIGHEST_PRECEDENCE。如果有其他相同顺序的过滤器,则必须增加它们的顺序(例如,通过将Ordered.HIGHEST_PRECEDENCE替换为Ordered.HIGHEST_PRECEDENCE + 1),使它们在我们的异常处理过滤器之后执行。
此外,您还需要确保您的过滤器在Spring Security过滤器链之前执行。因此,需要将application.properties中的security.filter-order属性设置为高于GlobalExceptionFilter顺序的某个值来更改Spring Security过滤器链的顺序。
security.filter-order=0

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


谢谢,这很有帮助。还有一个问题,为什么将异常过滤器设置为最高优先级?在我看来,它应该是最低的。我对顺序感到困惑。 - wl.GIG
我认为异常过滤器应该是链中的最后一个。这样它就可以捕获所有的异常。 - wl.GIG
1
我也觉得这个名字很令人困惑。如果你查看这个整数常量的值,你会发现它的值是Integer.MIN_VALUE。事实上,一个低顺序的过滤器比一个高顺序的过滤器具有更高的优先级。它们按升序“排序”。可能创建者给它起了这个名字,以强调赋予低顺序值的bean更高的优先级(优先权)。 - Marko Previsic
@wl.GIG 必须放在所有其他过滤器之前,因为它是链中的第一个过滤器,然后将请求转发给下一个过滤器,每个过滤器也将其转发到下一个过滤器。在过滤器完成其执行后,控制流返回到其前面的过滤器,因此在结尾处的控制流将返回到链中的第一个过滤器。 - Marko Previsic
我明白了。谢谢。 - wl.GIG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接