09 - 进阶场景:双令牌 / 多端登录 / 踢下线 / SSO
前面把登录的核心机制和安全都讲透了。这一章带你看几个真实产品里绕不开的进阶需求,理解它们在架构上是怎么落地的。
依然重思维:目标是让你”听得懂、说得清、会判断”,而不是给你一套可复制的代码。
一、Access / Refresh 双令牌:既要安全又要不频繁登录
矛盾在哪
第 07 章埋了个矛盾:
token 寿命设很长(如 7 天):用户不用老登录,体验好,但一旦被偷,攻击者能用很久 → 不安全
token 寿命设很短(如 15 分钟):安全,但用户每 15 分钟就要重新输密码 → 体验崩了
既要安全(短命),又要体验好(不用老登录),怎么办?——发两张令牌,各司其职。
双令牌怎么分工
┌────────────────────────────────────────────────────┐
│ Access Token(干活的) │
│ 寿命短:15 分钟 │
│ 用途:每次访问接口都带它 │
│ 特点:无状态,验签就行,就算被偷也只能用 15 分钟 │
├────────────────────────────────────────────────────┤
│ Refresh Token(续命的) │
│ 寿命长:7 天 │
│ 用途:只在 Access 过期时,用它去换一张新的 Access │
│ 特点:服务端存一份(Redis),能被作废 → 退出/踢人用它 │
└────────────────────────────────────────────────────┘
工作流程:
登录:服务端一次发两张:Access(15分钟) + Refresh(7天)
│
平时访问:带 Access → 正常干活
│
Access 过期了:
App 自动拿 Refresh 去 /refresh 接口换一张新 Access(用户完全无感)
│
Refresh 也过期了(7 天没动过):
才需要重新输密码登录
│
退出登录:服务端把这个 Refresh 作废(从 Redis 删掉)
→ 无法再续命 → 手里的 Access 最多再撑 15 分钟就死
这套设计的精妙之处:把”无状态、高频”的活儿交给短命的 Access(不查库、性能好),把”要能控制、低频”的活儿交给 Refresh(存 Redis、能作废)。每次接口请求不查库,只有十几分钟一次的刷新才查库。 既拿到了 JWT 的性能,又拿回了退出登录的控制力——这是第 05 章”混用”思想最优雅的落地。
二、多端登录 与 踢下线
真实产品对”同一账号能在几个设备登录”往往有明确要求。三种典型策略:
策略 A:允许多端同时在线(微信那种:手机、电脑、iPad 都能同时登)
策略 B:同一账号只能一端在线(很多银行 App:新设备登录 → 旧设备被挤下线)
策略 C:限制数量(如"最多同时 3 台")
怎么实现?关键是服务端要有一张”在线登录表”
纯无状态 JWT 做不到这些(服务端根本不知道谁在线)。必须在 Redis 里维护每个用户的登录记录:
Redis 里为每个用户存一个登录列表:
user:42:logins → [ 设备A的令牌id, 设备B的令牌id, ... ]
新设备登录时:
策略 B(单端):清空列表,只留新设备 → 旧设备的令牌一验就发现"不在列表里" → 被踢
策略 C(限 3 台):列表超过 3 个,就把最早的那个踢掉
“踢下线”的本质,其实就是第 07 章讲的”作废 token”:把某个设备的令牌从这张在线表里剔除(或拉进黑名单),它下次来验证时就被拒绝。所以你会发现:
多端登录、踢下线、退出登录、封号——本质是同一件事:服务端要能掌控”哪些令牌现在还算数”。 而这必然要求服务端存一份状态。
三、单点登录(SSO):一次登录,多个系统通用
要解决的问题
一家公司有很多系统:邮箱、OA、报销、Wiki……如果每个都要单独登录,员工要记一堆账号、登一堆次,很痛苦。
单点登录(SSO, Single Sign-On) 的目标:
登录一次,所有系统都认你。 退出一次,所有系统都退出。
核心思路(一句话认知)
把”登录/认证”这件事,从各个业务系统里**抽出来,交给一个专门的”认证中心”**统一负责:
┌──────────────────┐
│ 认证中心 SSO │ ← 只有它管登录、发凭证
└────────┬─────────┘
│ 你在这登录一次,拿到一个"通行凭证"
┌──────────────┼──────────────┐
▼ ▼ ▼
邮箱系统 OA 系统 报销系统
(不自己登录, (不自己登录, (不自己登录,
拿凭证去问 拿凭证去问 拿凭证去问
认证中心: 认证中心: 认证中心:
"这人是谁?") "这人是谁?") "这人是谁?")
流程感受一下:
你访问 OA 系统 → OA 发现你没登录 → 把你重定向到认证中心
→ 你在认证中心登录(就这一次)→ 认证中心发给你一个凭证
→ 带着凭证回到 OA → OA 拿凭证向认证中心确认 → 认你,放行
接着你访问报销系统 → 报销发现你没登录 → 重定向到认证中心
→ 认证中心一看:"你刚登录过啊" → 不用再输密码,直接发凭证
→ 回到报销系统 → 放行 ✅(你感觉"根本没登录就进去了")
- 你在业务里熟悉的 OAuth2 / OpenID Connect,就是实现这套”认证中心 + 各系统信任它”的标准协议。
- “用微信/Google 账号登录别的网站”,本质也是 SSO 的思想——微信/Google 就是那个被大家信任的认证中心。
SSO 是个大话题,这里你只要建立这个认知:把认证从各系统抽出来集中管理,各系统信任统一的认证中心。 细节(协议流程、令牌交换)真要落地时再深入。
小结
- 双令牌:短命 Access(无状态、高频、不查库)+ 长命 Refresh(存 Redis、能作废、低频刷新)。既要安全又要体验,是最主流的工程解法。
- 多端登录 / 踢下线:靠 Redis 维护每个用户的”在线登录表”,控制”同时几端""挤掉旧的”。本质是”服务端掌控哪些令牌还算数”。
- 多端登录、踢下线、退出、封号是同一类问题,都要求服务端存状态——纯无状态 JWT 做不到。
- SSO:把认证从各业务系统抽出来交给统一的”认证中心”,一次登录、处处通行;OAuth2 / OIDC 是其标准协议,“第三方账号登录”是其典型应用。
- 贯穿全篇的一条主线:要多少”控制力”,就得存多少”状态”。 这是登录架构里永恒的权衡。
最后一章,我们用一张决策树和一份避坑清单,把这十章的内容收口。
上一章 ← 08 - 绕不开的安全问题 | 下一章 → 10 - 总结与决策树 | 回到 README 目录