Spring认证过滤器抛出的异常错误信息不符合预期如何解决?
@ControllerAdvice 仅能捕获Spring MVC Controller层抛出的异常,自定义身份认证过滤器的执行顺序在DispatcherServlet之前,你在过滤器中抛出的IrrecoverableAuthException会直接被Spring Security内置的异常处理过滤器捕获,走默认的认证失败逻辑,根本无法触发你定义的全局异常处理器,所以会返回系统默认的「Full authentication access is required to access this resource」提示。
方案1:在过滤器内直接捕获异常手动返回响应
这是最直接的方案,不需要修改其他配置,只需调整你的过滤器代码,对认证逻辑做异常捕获,匹配到自定义认证异常时直接构造你需要的返回体写入响应即可,代码示例:
@Slf4j // 建议去掉@Component注解,避免过滤器被Spring Boot自动注册到全局过滤链导致重复执行 public class TokenValidationFilter extends OncePerRequestFilter { @Autowired private TokenValidationHelper tokenValidationHelper; // 注入ObjectMapper用于序列化错误响应 @Autowired private ObjectMapper objectMapper; @Override protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException { HttpServletRequest httpRequest = (HttpServletRequest)servletRequest; HttpServletResponse httpResponse = (HttpServletResponse)servletResponse; MultiReadRequestWrapper request = new MultiReadRequestWrapper(httpRequest); SecurityContext context = SecurityContextHolder.getContext(); // check if already authenticated if (context.getAuthentication() == null) { try { Authentication authentication = tokenValidationHelper.validateAndAuthenticate(request); context.setAuthentication(authentication); } catch (IrrecoverableAuthException e) { // 手动构造错误响应 httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); httpResponse.setContentType("application/json;charset=UTF-8"); RegistrationErrorResponse errorResponse = getErrorResponse(e, Category.Error, e.getMessage()); httpResponse.getWriter().write(objectMapper.writeValueAsString(errorResponse)); // 直接返回,不再继续走后续过滤链 return; } } filterChain.doFilter(request, httpResponse); } // 这里把你异常处理器里的getErrorResponse逻辑挪过来,或者抽成公共工具方法调用即可 private RegistrationErrorResponse getErrorResponse(IrrecoverableAuthException e, Category error, String message) { // 你的错误响应构造逻辑 } }调整后记得在Spring Security配置类中,手动将该过滤器添加到
UsernamePasswordAuthenticationFilter之前执行即可。方案2:自定义Spring Security认证入口点统一处理
如果你希望所有认证相关异常统一走公共处理逻辑,可以自定义
AuthenticationEntryPoint,在里面实现错误响应构造逻辑,然后在Spring Security配置中把自定义入口点注册进去,所有Spring Security捕获到的认证异常都会走这个入口点的处理逻辑,和你的全局异常处理器效果一致。
你贴出的异常处理器代码存在语法错误,getErrorResponse(exception , Category.Error exception.getMessage()) 两个参数之间缺少逗号,修正为getErrorResponse(exception, Category.Error, exception.getMessage())即可正常编译。
内容的提问来源于stack exchange,提问作者lwjmexppgkjpph

