Spring Security过滤器异常处理:自定义Token过期提示返回客户端
解决方案
要让Token过期时返回自定义提示并覆盖Spring Security默认异常行为,按以下步骤调整:
1. 让自定义异常继承AuthenticationException
Spring Security仅会将继承自AuthenticationException的异常视为认证相关异常,交由AuthenticationEntryPoint处理。修改你的TokenExpiredException:
public class TokenExpiredException extends AuthenticationException { public TokenExpiredException(String msg, Instant timestamp) { super(msg); // 可按需添加自定义字段(如timestamp) } }
2. 调整AuthenticationEntryPoint,针对性处理自定义异常
在你的认证入口点实现中,识别TokenExpiredException并返回自定义响应,避免统一返回通用认证错误:
@Autowired @Qualifier("handlerExceptionResolver") private HandlerExceptionResolver resolver; @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { if (authException instanceof TokenExpiredException) { // 设置响应状态码为401(未授权) response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json;charset=UTF-8"); // 构造自定义JSON响应 String json = String.format("{\"message\":\"%s\",\"status\":401}", authException.getMessage()); response.getWriter().write(json); } else { // 其他认证异常交给默认处理器处理 resolver.resolveException(request, response, null, authException); } }
3. 确保过滤器中异常正确传递
检查你的JwtAuthFilter的doFilterInternal方法,确保调用validateToken时抛出的TokenExpiredException没有被内部捕获,而是向上抛出给Spring Security的异常处理机制:
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = // 从请求中提取token的逻辑 try { if (token != null) { Authentication auth = userAuthenticationProvider.validateToken(token, request); if (auth != null) { SecurityContextHolder.getContext().setAuthentication(auth); } } filterChain.doFilter(request, response); } catch (TokenExpiredException e) { // 直接抛出,让AuthenticationEntryPoint处理 throw e; } }
4. 可选:全局异常处理器兜底(配合Resolver使用)
如果希望通过全局异常处理器统一管理异常,可以添加@RestControllerAdvice类,确保TokenExpiredException被正确捕获:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(TokenExpiredException.class) public ResponseEntity<Map<String, Object>> handleTokenExpired(TokenExpiredException e) { Map<String, Object> resp = new HashMap<>(); resp.put("message", e.getMessage()); resp.put("status", HttpStatus.UNAUTHORIZED.value()); return new ResponseEntity<>(resp, HttpStatus.UNAUTHORIZED); } }
调整完成后,当Token过期时,客户端会收到状态码401和你自定义的"Session expired, please login again"提示,而非默认的500错误或通用认证异常。
内容的提问来源于stack exchange,提问作者pappu_kutty
相关产品推荐
相关产品推荐

