You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:40:27