令牌类型详解:JWT、OAuth2.0、Bearer、Refresh、SAML
大家好,我是老周。今天咱们来聊聊令牌的类型。说实话,很多安全漏洞的根源,就是开发者没搞清楚自己手里拿的到底是什么令牌。
我见过不少项目,代码里混着 JWT 和 OAuth2.0 的概念,结果出了安全问题还一头雾水。所以这一章,咱们把五种最常见的令牌掰开揉碎了讲清楚。
JWT 令牌结构:三段式,每一段都有讲究
JWT(JSON Web Token)是目前最流行的令牌格式。它的结构很简单——三个点分隔的 Base64 字符串。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这三段分别是:
- Header(头部):声明签名算法和令牌类型
- Payload(载荷):存放实际数据,比如用户 ID、过期时间
- Signature(签名):防止数据被篡改
我个人习惯在 Payload 里只放三个字段:sub(用户标识)、exp(过期时间)、iat(签发时间)。够用,而且安全。
OAuth2.0 令牌:授权框架的核心产物
OAuth2.0 本身不是令牌,而是一个授权框架。它定义了四种授权模式,每种模式产出的令牌用途不同。
| 授权模式 | 适用场景 | 安全等级 |
|---|---|---|
| 授权码模式 | 第三方应用访问用户资源 | ⭐⭐⭐⭐⭐ |
| 隐式模式 | 纯前端应用(已不推荐) | ⭐⭐ |
| 密码模式 | 自家应用,高度信任 | ⭐⭐⭐ |
| 客户端凭证模式 | 服务间通信 | ⭐⭐⭐⭐ |
我曾经接手过一个项目,他们用密码模式做第三方登录。你想想看,用户的账号密码直接交给第三方应用,这风险有多大?后来我强制改成了授权码模式,配合 PKCE 扩展,才算把漏洞堵上。
Bearer 令牌:谁持有,谁使用
Bearer 令牌是最常见的令牌使用方式。它的核心思想很简单:只要你能出示这个令牌,我就认你。
HTTP 请求中通常这样携带:
Authorization: Bearer <token>
嗯,这里要注意。Bearer 令牌最大的弱点就是——它太简单了。只要令牌泄露,任何人都能冒充用户。所以:
- 必须使用 HTTPS 传输
- 令牌有效期要短(我一般设 15 分钟)
- 不要在 URL 参数中传递令牌
Refresh 令牌:长寿命的秘密武器
Access Token 有效期短,但用户不能老登录啊。这时候就需要 Refresh Token 出场了。
它的工作流程是这样的:
- 用户登录,同时拿到 Access Token(15分钟有效)和 Refresh Token(7天有效)
- Access Token 过期后,客户端用 Refresh Token 去请求新的 Access Token
- 服务器验证 Refresh Token 有效,颁发新的 Access Token
- Refresh Token 也可以轮换——每次使用后发一个新的
我个人强烈建议开启 Refresh Token 轮换。为什么?因为如果 Refresh Token 被偷了,攻击者只能用它一次。你想想看,这相当于给令牌加了一道保险。
核心原则:
- Access Token:短命(分钟级),频繁传输
- Refresh Token:长命(天级),只在刷新时传输
- Refresh Token 必须存储在安全位置(HttpOnly Cookie 或安全存储)
SAML 令牌:企业级的老大哥
SAML(Security Assertion Markup Language)令牌是 XML 格式的,主要用于企业单点登录(SSO)。
它的结构比 JWT 复杂得多:
<saml:Assertion>
<saml:Issuer>https://idp.example.com</saml:Issuer>
<saml:Subject>
<saml:NameID>user@example.com</saml:NameID>
</saml:Subject>
<saml:Conditions NotBefore="..." NotOnOrAfter="..." />
<saml:AuthnStatement AuthnInstant="..." />
</saml:Assertion>
SAML 的优势在于:
- 支持复杂的属性声明
- 内置签名和加密机制
- 企业级成熟度高
但缺点也很明显:XML 解析慢、配置复杂、调试困难。我在做金融项目时遇到过 SAML 响应被篡改的案例——因为开发者忘了验证签名。嗯,XML 签名验证的坑特别多,一定要用成熟的库,别自己手写。
五种令牌对比一览
| 令牌类型 | 格式 | 是否自包含 | 典型用途 | 安全要点 |
|---|---|---|---|---|
| JWT | JSON + Base64 | 是 | API 认证、信息交换 | 验证签名、不存敏感信息 |
| OAuth2.0 Token | 不固定(通常是 JWT) | 视实现而定 | 授权委托 | 使用授权码模式 + PKCE |
| Bearer Token | 不固定 | 否 | HTTP 认证 | HTTPS 传输、短有效期 |
| Refresh Token | 不固定 | 否 | 获取新的 Access Token | 轮换机制、安全存储 |
| SAML Assertion | XML | 是 | 企业 SSO | 验证 XML 签名、防重放 |
令牌关系全景图
下面这张图展示了五种令牌之间的关系和流转路径。我建议你保存下来,以后设计系统时对照着看。
选型建议:别让令牌成为你的短板
说了这么多,到底该怎么选?我总结几条实战经验:
- 新项目:JWT + OAuth2.0 授权码模式 + PKCE,这是目前最稳妥的组合
- 微服务架构:JWT 做服务间认证,配合客户端凭证模式
- 企业 SSO:SAML 或 OAuth2.0 + OpenID Connect,看现有基础设施
- 移动端:一定要用 PKCE,别用隐式模式
好了,这一章的内容就到这里。记住,令牌不是随便拼个字符串就完事的。每种令牌都有自己的脾气,摸透了才能用好它。