令牌类型详解:JWT、OAuth2.0、Bearer、Refresh、SAML

大家好,我是老周。今天咱们来聊聊令牌的类型。说实话,很多安全漏洞的根源,就是开发者没搞清楚自己手里拿的到底是什么令牌。

我见过不少项目,代码里混着 JWT 和 OAuth2.0 的概念,结果出了安全问题还一头雾水。所以这一章,咱们把五种最常见的令牌掰开揉碎了讲清楚。

JWT 令牌结构:三段式,每一段都有讲究

JWT(JSON Web Token)是目前最流行的令牌格式。它的结构很简单——三个点分隔的 Base64 字符串。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

这三段分别是:

  • Header(头部):声明签名算法和令牌类型
  • Payload(载荷):存放实际数据,比如用户 ID、过期时间
  • Signature(签名):防止数据被篡改
⚠️ 重要提醒:Payload 只是 Base64 编码,不是加密!任何人都可以解码看到里面的内容。千万不要把密码、信用卡号等敏感信息放进去。

我个人习惯在 Payload 里只放三个字段:sub(用户标识)、exp(过期时间)、iat(签发时间)。够用,而且安全。

OAuth2.0 令牌:授权框架的核心产物

OAuth2.0 本身不是令牌,而是一个授权框架。它定义了四种授权模式,每种模式产出的令牌用途不同。

授权模式 适用场景 安全等级
授权码模式 第三方应用访问用户资源 ⭐⭐⭐⭐⭐
隐式模式 纯前端应用(已不推荐) ⭐⭐
密码模式 自家应用,高度信任 ⭐⭐⭐
客户端凭证模式 服务间通信 ⭐⭐⭐⭐

我曾经接手过一个项目,他们用密码模式做第三方登录。你想想看,用户的账号密码直接交给第三方应用,这风险有多大?后来我强制改成了授权码模式,配合 PKCE 扩展,才算把漏洞堵上。

Bearer 令牌:谁持有,谁使用

Bearer 令牌是最常见的令牌使用方式。它的核心思想很简单:只要你能出示这个令牌,我就认你。

HTTP 请求中通常这样携带:

Authorization: Bearer <token>

嗯,这里要注意。Bearer 令牌最大的弱点就是——它太简单了。只要令牌泄露,任何人都能冒充用户。所以:

  • 必须使用 HTTPS 传输
  • 令牌有效期要短(我一般设 15 分钟)
  • 不要在 URL 参数中传递令牌
💡 我的经验:曾经有个客户把 Bearer 令牌放在 URL 里,结果被浏览器历史记录、代理日志、Referer 头一路泄露。最后整个用户数据库都被拖走了。从那以后,我见到 URL 里传令牌的代码就直接打回。

Refresh 令牌:长寿命的秘密武器

Access Token 有效期短,但用户不能老登录啊。这时候就需要 Refresh Token 出场了。

它的工作流程是这样的:

  1. 用户登录,同时拿到 Access Token(15分钟有效)和 Refresh Token(7天有效)
  2. Access Token 过期后,客户端用 Refresh Token 去请求新的 Access Token
  3. 服务器验证 Refresh Token 有效,颁发新的 Access Token
  4. 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 签名、防重放

令牌关系全景图

下面这张图展示了五种令牌之间的关系和流转路径。我建议你保存下来,以后设计系统时对照着看。

令牌类型关系与流转图 OAuth2.0 授权框架 JWT 令牌格式 Bearer 令牌使用方式 Refresh 令牌 SAML 断言 💡 关键理解 OAuth2.0 是框架,JWT 是格式 Bearer 是使用方式,Refresh 是补充机制 常用格式 默认使用方式 扩展机制 企业场景 🔑 实战建议 1. 新项目优先选 JWT + OAuth2.0 授权码模式 2. Access Token 用 Bearer 方式,有效期 15 分钟 3. Refresh Token 必须轮换,存储在 HttpOnly Cookie 4. 企业 SSO 场景才考虑 SAML,别杀鸡用牛刀

选型建议:别让令牌成为你的短板

说了这么多,到底该怎么选?我总结几条实战经验:

  • 新项目:JWT + OAuth2.0 授权码模式 + PKCE,这是目前最稳妥的组合
  • 微服务架构:JWT 做服务间认证,配合客户端凭证模式
  • 企业 SSO:SAML 或 OAuth2.0 + OpenID Connect,看现有基础设施
  • 移动端:一定要用 PKCE,别用隐式模式
💡 我的习惯:每次设计令牌方案前,先问自己三个问题——令牌在哪里生成?在哪里验证?泄露了怎么办?这三个问题想清楚,80% 的安全问题就避免了。

好了,这一章的内容就到这里。记住,令牌不是随便拼个字符串就完事的。每种令牌都有自己的脾气,摸透了才能用好它。