Spring Boot 集成 JWT 的最佳实践及刷新令牌相关问题咨询
刷新令牌常见实践问题解答
1. 刷新令牌是否必须存入数据库?
刷新令牌没有强制要求必须存入数据库,存储方案完全可以根据项目的安全要求、迭代成本选择,常见的符合最佳实践的替代方案如下:
- 无状态签名刷新令牌:和JWT访问令牌逻辑一致,将用户ID、过期时间、权限标识等核心字段加密签名后直接下发给客户端,后端不做任何存储。这种方案实现成本最低,适合小型个人项目、安全要求较低的内部系统,缺点是无法主动作废未过期的刷新令牌,除非额外维护黑名单机制。
- 分布式缓存存储:将刷新令牌存在Redis这类支持TTL的分布式缓存中,是目前中大型业务系统的主流选择。相比数据库存储,缓存读写性能更高,还可以直接给令牌设置过期时间,到期后自动清理,无需额外开发清理逻辑,同时也支持主动删除令牌实现用户登出、密码修改后的权限失效。
- 客户端HttpOnly安全Cookie存储:将刷新令牌加密后存入客户端带
HttpOnly、Secure、SameSite属性的Cookie中,后端只做签名校验不存储,这种方案可以降低XSS攻击泄露令牌的风险,缺点是跨域场景适配成本较高,同样存在无法主动作废令牌的问题。
很多教程示例选择存入数据库,主要是为了方便实现主动权限管控,比如可以绑定刷新令牌的使用设备、IP、使用次数,出现异常操作时可以立刻作废对应令牌,安全可控性更高。
2. 存入数据库时的过期令牌清理方案
你可以通过Spring定时任务实现清理,但这不是唯一的可选方案:
- Spring定时任务实现:只需要在启动类加上
@EnableScheduling注解,然后编写定时方法用@Scheduled配置执行周期,比如设置为每天低峰期(如凌晨2点)执行一次SQL删除所有expire_time小于当前时间的刷新令牌即可,实现非常简单,适合单实例或定时任务做了分布式锁的集群项目。 - 惰性清理:每次用户调用刷新令牌接口时,先校验对应令牌是否过期,如果已经过期就直接在数据库中删除该令牌,同时可以配置每次查询令牌时按概率触发一次全表过期数据清理,不需要额外维护定时任务,缺点是如果长时间没有用户使用刷新令牌,过期数据会一直占用数据库存储空间。
- 数据库自动清理:如果使用的是MongoDB这类支持TTL索引的数据库,可以直接给过期时间字段创建TTL索引,数据库会自动清理到期数据;如果使用MySQL,也可以开启事件调度器,配置定时任务在数据库层面执行删除操作,无需占用应用层资源。
内容的提问来源于stack exchange,提问作者M.Cyber
相关产品推荐
相关产品推荐

