Spring Security 5.2+不再提供ExpiredTokenException,因令牌过期被统一归为InvalidTokenException,体现“无效令牌”分层设计;JWT过期、签名错误、nbf/iat校验失败等均抛此异常,具体原因需通过cause或消息判断。

Java中OAuth2令牌过期时,Spring Security默认抛出的是InvalidTokenException(来自spring-security-oauth2-resource-server),而不是ExpiredTokenException。因为Spring Security 5.2+已弃用旧的spring-security-oauth,也不再提供ExpiredTokenException这个类。
为什么没有 ExpiredTokenException?
Spring Security官方认为:令牌过期属于“无效令牌”的一种具体原因,统一由InvalidTokenException表示更符合分层设计。JWT解析失败、签名错误、过期、不满足nbf/iat等校验,都会触发同一个异常类型,具体原因可通过异常消息或嵌套原因判断。
如何识别并区分过期场景?
在自定义异常处理器(如AuthenticationEntryPoint或BearerTokenResolver后置处理)中,可检查InvalidTokenException的cause是否为JwtException子类,再判断是否含“expired”关键词:
-
推荐方式(解析JWT手动校验):使用
JwtDecoder解码后,调用jwt.getExpiresAt()与当前时间比对 -
快速判断(异常消息匹配):
e.getMessage().toLowerCase().contains("expired") -
精准判断(检查cause):若cause是
JwtTimestampRejectedException(Spring Security内部抛出),说明明确因过期被拒绝
如何自定义抛出 ExpiredTokenException?
如果你项目中已有ExpiredTokenException(比如自定义异常类),可在资源服务器的认证过滤器链中拦截并转换:
- 继承
BearerTokenAuthenticationFilter,重写doFilterInternal,捕获InvalidTokenException后做条件转换 - 更轻量方式:配置
OAuth2ResourceServerConfigurer的jwt(jwt -> jwt.jwtAuthenticationConverter(...)),在converter中提前解码并主动抛出自定义异常 - 示例逻辑:if (jwt.getExpiresAt().before(new Date())) throw new ExpiredTokenException("Token expired");
注意兼容性与最佳实践
直接抛ExpiredTokenException需确保它继承自AuthenticationException(否则Spring Security不会按未认证流程处理)。但更推荐沿用标准异常体系,在响应体中通过error字段明确返回"error": "token_expired",前端据此区分处理——这比自定义异常类更利于API契约稳定。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











