令牌类型选型:JWT、Opaque 、Paseto、SAML
说实话,选令牌类型是令牌化设计里最纠结的一步。我记得有个项目上线前一周还在纠结用JWT还是Opaque ,最后选了后者,因为客户要求能随时撤销令牌。今天我就带你把主流四种令牌类型挨个扒一扒。
JWT(JSON Web )
JWT 现在太火了,几乎成了 API 令牌的默认选项。它的核心特点是自包含——令牌本身存了用户信息、过期时间、权限范围,服务端不用查数据库就能验证。
| 维度 | 说明 |
|---|---|
| 优点 | 无状态、跨语言、可包含自定义声明、支持签名和加密 |
| 缺点 | 负载无法撤销(除非黑名单)、令牌体积大、签名验证有性能开销 |
| 适用场景 | 短时效令牌、微服务间认证、移动端 |
我曾经在项目里直接用 JWT 的 payload 存了大段用户权限列表,结果 大小飙到 4KB,每次请求都传输,带宽白白浪费。后来改成只存 role_id,接口再查权限。
为什么说 JWT 难撤销?因为它本身就是个「活期存单」,到期前谁拿着都能用。你想想看,如果用户改了密码,旧 依然有效,得把签发密钥改了才行。我的习惯是 JWT 过期时间控制在 15 分钟以内,配合 refresh 做长生命周期。
Opaque (不透明令牌)
说白了就是个随机字符串,像个房间钥匙——你看到钥匙也不知道哪个房间,得拿到前台(授权服务器)查一下。这种令牌就是一把无意义的 ID,所有信息都保存在服务端。
需要支持令牌撤销、需要控制令牌生命周期、多端共享令牌状态。比如 OAuth 2.0 的 Bearer 默认就是不透明的。
| 维度 | 说明 |
|---|---|
| 优点 | 可撤销、体积小(通常 32-64 字节)、无信息泄露风险 |
| 缺点 | 需查数据库 / 缓存、增加网络延迟、依赖中心化存储 |
| 适用场景 | 会话管理、高安全性要求、需要即时失效 |
我个人习惯在微服务网关层做 Opaque 的校验——网关统一查 Redis,后端服务直接信任网关传过来的用户信息。这样后端服务不用改代码就能全局控制令牌。
Paseto(Platform-Agnostic Security )
我记得第一次看到 Paseto 是 2019 年,当时 JWT 的漏洞层出不穷(alg=none、密钥混淆),Paseto 的创建者直接说:「JWT 的设计是失败的」。Paseto 把加密和签名算法固化为两种模式:本地模式用对称加密,公共模式用非对称签名。你没法选「无签名」这种邪恶选项。
| 维度 | 说明 |
|---|---|
| 优点 | 安全默认、算法固定、防止签名混淆、版本化设计 |
| 缺点 | 生态较小(库少)、社区支持弱、学习曲线陡 |
| 适用场景 | 对安全极端敏感、新项目可接受额外复杂度 |
我曾经在内部工具链里尝试用 Paseto 替换 JWT,发现 Go 和 Python 的库都挺成熟了,但 Java 库还不太稳定。如果团队全是 Java 生态,建议再观望。
SAML(Security Assertion Markup Language)
SAML 是「上一代」的令牌标准,主要用在企业级单点登录(SSO)。它基于 XML,结构臃肿,一个断言动不动就几十 KB。嗯,现在除了金融、政府老系统,基本没人用它做 REST API 令牌。
| 维度 | |
|---|---|
| 优点 | 支持跨域 SSO、标准成熟、支持复杂的属性映射 |
| 缺点 | XML 解析慢、体积大、移动端不友好、配置繁琐 |
| 适用场景 | 遗留企业系统集成、政府 / 金融内部 SSO(非 API 调用) |
你想想看,移动端一个 50KB 的 SAML 断言传回来,网络稍微差一点就超时了。所以 REST API 场景下我基本不考虑它,除非客户明确要求对接老旧的 SAML IdP。
四种令牌类型对比总览
| 类型 | 存储方式 | 可撤销 | 体积 | 安全等级 | 生态成熟度 |
|---|---|---|---|---|---|
| JWT | 自包含 | 否(需黑名单) | 大(通常 1-2KB) | 中等 | ⭐⭐⭐⭐⭐ |
| Opaque | 服务端 | 是 | 小(32-64B) | 高 | ⭐⭐⭐⭐⭐ |
| Paseto | 自包含 | 否(同 JWT) | 小(类似 JWT) | 高 | ⭐⭐⭐ |
| SAML | 自包含 | 否 | 极大(10KB+) | 高 | ⭐⭐⭐⭐ |
实战选型流程图
下面这张图能帮你快速决策。我每次做架构评审都会走一遍这个流程。
选型建议
- 普通 Web API / 移动端:JWT + 短过期(15分钟),用 refresh 延长。我见过大量项目这样跑,没什么大问题。
- 高安全场景(金融、医疗):Opaque 为主,配合 Redis 存储,支持即时撤销。成本是每次请求多一次网络开销,但安全换性能值得。
- 新项目想尝鲜:可以试试 Paseto。不过要做好库出问题时的降级预案,我就是因为找不到好用的 .NET 库才放弃的。
- 与遗留 SSO 对接:SAML 逃不掉,但尽量在 API 网关处转成内部 JWT,别让下游服务直接处理 SAML。
你可以用 Opaque 做入口令牌(接收端校验),然后在网关内部签发一个短时效 JWT 给下游微服务。这样既支持撤销,又享受 JWT 的无状态便利。
嗯,四种令牌的对比就这些了。没有银弹,只有权衡。下回你做设计时带着这张决策图走一遍,基本不会跑偏。对了,记得把令牌的序列化和签名算法也写进 API 文档,我曾经遇到过服务端升级算法后客户端没更新,直接 401 一片红……