登录态看起来是个小功能,但一旦选错方案,后面做多端登录、强制下线、权限变更都会很别扭。把三种常见方案的取舍理清楚。
一、服务端 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 -
最后修改:2024年9月12日
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/archives/710
共有 0 条评论