refresh_token 通常不是标准jwt,可能是opaque token、对称加密串或数据库记录,直接pyjwt解码易报错;需先确认其格式与签名方式,否则应调用后端刷新接口。

refresh_token 为什么不能直接用 PyJWT 解码验证?
因为 refresh_token 通常不走标准 JWT 签名验证流程——它可能被设计为 opaque token(黑盒字符串),或用对称密钥加密而非签名,甚至只是数据库里一条带过期时间的记录。直接拿 jwt.decode() 去解,大概率抛 InvalidSignatureError 或 DecodeError。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先确认你的 refresh token 是不是真 JWT:检查它是否由三段 Base64Url 字符串组成(
xxx.yyy.zzz),且后端文档明确写了“signed with HS256” - 如果不是,别硬解——应调用后端专属刷新接口,比如
POST /auth/refresh,把refresh_token当普通字段传过去 - 如果是,但用的是非标准密钥(比如从 DB 查出的用户专属密钥),必须确保解码时传入正确的
key和algorithms,否则jwt.decode(token, key, algorithms=["HS256"])会静默失败
access_token 过期后,前端怎么安全触发刷新?
不能等用户点按钮才去刷新,更不能在每次请求前都无脑调刷新接口——这既浪费资源,又可能因并发导致 token 被误废。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 在发起受保护 API 请求前,先检查
access_token的exp声明是否已过期(用jwt.decode(token, options={"verify_signature": False})取出exp,转成时间戳比对) - 如果快过期(比如剩余
- 必须加锁:多个请求同时发现 token 过期时,只允许一个刷新请求发出,其余等待其完成并复用新 token,避免重复刷新或 401 雪崩
刷新成功后,旧 access_token 还能用吗?
能,除非你主动让它失效。JWT 默认是无状态的,服务端不会“吊销”已签发的 token,只靠过期时间控制生命周期。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 如果业务要求“单设备登录”或“强制登出”,不能只依赖
exp,得引入黑名单机制:把刚刷新掉的access_token的jti存到 Redis,设 TTL 略长于原 token 过期时间 - 刷新接口返回的新
access_token应该带新jti和新exp,而refresh_token本身也建议滚动更新(即每次刷新后发个新的,旧的立即作废) - 注意:滚动
refresh_token时,必须同步更新客户端本地存储,否则下次刷新会因 token 已失效而失败
Python 后端用 PyJWT 实现刷新接口时,最常漏掉的校验
很多人只校验 refresh_token 是否签名有效、是否过期,却忘了最关键的一步:确认这个 token 确实属于当前用户,且没被滥用。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 必须验证
refresh_token中的sub(用户 ID)和jti(唯一标识)是否匹配数据库中该用户的最新记录 - 检查
refresh_token的使用次数或时间窗口:比如限制 24 小时内最多刷新 10 次,防止暴力重放 - 别忽略
nbf(not before)声明——有些系统会用它标记 token 生效起始时间,早于该时间的刷新请求应拒绝 - 生成新
access_token时,exp值别写死,应基于当前时间动态计算,别直接复制旧 token 的exp
真正麻烦的从来不是怎么生成 token,而是怎么让每个 refresh_token 只被用一次、只被对应的人用、只在该用的时候用。










