新版Spring Authorization Server中Token撤销功能失效问题
OAuth2 /oauth2/revoke端点的预期行为及Spring实现问题解析
一、OAuth2规范里的令牌撤销预期
按照OAuth2令牌撤销的RFC 7009标准:
- 令牌撤销的核心目的是让令牌立刻失效,不能再用来发起授权请求。
- 规范没强制要求必须从数据库删除令牌,只要求授权服务器不再接受该令牌的验证请求。常见的实现方式有三种:
- 把令牌标记为已撤销状态(存入黑名单或撤销列表)
- 直接删除数据库里的令牌记录
- 连带失效关联的刷新令牌等凭证
二、Spring默认撤销端点失效的常见原因
Spring Security OAuth2的默认/oauth2/revoke端点经常会出现撤销后令牌还能用的情况,主要是这几个原因:
- 令牌存储的撤销逻辑没配置到位:
如果用的是JdbcTokenStore,默认的撤销操作只会移除令牌的关联元数据(比如刷新令牌),不会把访问令牌标记为失效。得自己扩展逻辑,撤销时给访问令牌加个已撤销的状态标记,或者直接加入黑名单。 - JWT等无状态令牌的特性限制:
JWT是自包含的令牌,授权服务器默认不会存储它的状态。这时候撤销端点没法直接让已签发的JWT失效,除非你实现令牌黑名单机制(比如把撤销的JWT的唯一标识jti存到Redis,验证的时候查黑名单),或者把JWT的有效期设得短一些。 - 资源服务器没检查令牌撤销状态:
就算你执行了撤销操作,如果资源服务器验证令牌的时候,没去查授权服务器的撤销状态(或者本地的黑名单),那只要令牌没过期,还是会被接受。
三、修复Spring令牌撤销功能的具体做法
- 针对
JdbcTokenStore:- 扩展
JdbcTokenStore的revokeToken方法,添加更新令牌状态的逻辑(比如在令牌表加个revoked字段,撤销时设为true)。 - 配置资源服务器,在验证令牌时必须查询这个撤销状态。
- 扩展
- 针对JWT令牌:
- 用Redis做缓存实现令牌黑名单,撤销时把JWT的jti存入黑名单,过期时间和JWT的有效期保持一致。
- 自定义JWT验证过滤器,每次验证前先检查jti是否在黑名单里。
- 调用撤销端点时要传对参数:
调用/oauth2/revoke的时候,必须指定token_type_hint参数,值为access_token或者refresh_token,不然服务器可能只处理刷新令牌,不管访问令牌。
内容的提问来源于stack exchange,提问作者Andrew Zabur
相关产品推荐
相关产品推荐

