Session、JWT 与刷新令牌:登录态方案怎么选

米阳 2024-9-12 5 9/12

登录态看起来是个小功能,但一旦选错方案,后面做多端登录、强制下线、权限变更都会很别扭。把三种常见方案的取舍理清楚。

一、服务端 Session

服务端保存会话状态,浏览器只拿一个随机 session_id。

Cookie: sid=9c3f...  →  Redis: sid → {user_id, 权限, 过期时间}

优点:服务端完全掌控,改权限立即生效,踢人只需删一条记录,实现简单,天然支持滑动过期。

代价是每次请求都要查一次会话存储,多实例部署需要共享 Redis 或做粘性会话。对绝大多数单体或中小规模后台,这仍然是最省心的选择。

二、JWT:无状态但有代价

JWT 把用户信息签在令牌里,服务端不存状态,校验签名即可。适合服务间调用、第三方开放接口、多个服务各自校验的场景。

它的问题也正来自「无状态」:

  • 签发了就收不回来:除非额外维护黑名单,否则改密码、强制下线都要等令牌自然过期
  • 权限变更不即时:令牌里的角色是签发那一刻的快照
  • 体积:塞的字段越多,每个请求头越大
  • 密钥轮换要设计好 kid,否则新旧令牌无法共存

所以如果选 JWT,访问令牌有效期一定要短(5~15 分钟)。

三、双令牌:短 access + 长 refresh

这是目前比较平衡的做法:

access_token  15 分钟,只用于调接口,不落库
refresh_token  7~30 天,存服务端(可撤销),仅用于换新的 access_token

刷新时校验 refresh_token 是否已被撤销、是否被重复使用。重复使用检测很关键:一旦发现同一个 refresh_token 被用第二次,说明可能已泄露,应立即让整条令牌链失效。

配合「绝对过期时间」(比如距首次登录最多 30 天)和「空闲过期」(连续 7 天无操作需重新登录),安全性会更完整。

四、传输与存储细节

  • 全站 HTTPS,Cookie 加 HttpOnly + Secure + SameSite=Lax
  • 令牌别放 URL、别写进日志、别存 localStorage(XSS 可直接读走)
  • 涉及改密、支付、改绑手机的操作,要求二次验证,不要只靠登录态
  • 登出时服务端要真的让 refresh_token 失效,只清前端 Cookie 不算登出

小结

普通后台优先 Session + Redis;确实需要跨服务无状态校验再上 JWT,并且必须配短期 access_token 与可撤销的 refresh_token。判断标准很简单:你是否需要「立刻让某个用户失效」这个能力。

- THE END -

米阳

9月12日09:15

最后修改:2024年9月12日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论