JWT 结构说明

最后更新:

JWT(JSON Web Token)是一种紧凑的、URL 安全的字符串,用来在各方之间传递声明(claims)。Supabase Auth、OAuth 2.0 等场景都依赖它传递用户身份。

阅读前提

若想流畅阅读本文,建议已具备:


基本格式

JWT 由 三部分 组成,用点号 . 连接:

Header.Payload.Signature

例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

每一部分都是 Base64URL 编码 的 JSON(签名部分除外,它是二进制结果的编码)。


描述 token 的元数据和签名算法,通常是 JSON:

{
  "alg": "HS256",
  "typ": "JWT"
}
字段 含义
alg 签名算法,如 HS256RS256ES256
typ 类型,固定为 JWT

编码后成为 JWT 的 第一段


Payload

存放实际数据,即 claims(声明)。也是 JSON 对象:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}
字段 全称 含义
iss Issuer 签发者
sub Subject 主题(通常是用户 ID)
aud Audience 接收方
exp Expiration Time 过期时间(Unix 时间戳)
nbf Not Before 生效时间
iat Issued At 签发时间
jti JWT ID 唯一标识

还可以放 自定义字段,比如 roleemail 等。在 Supabase 签发的 JWT 中,sub 通常对应 auth.users.idrole 常为 authenticatedanon

注意:Payload 只是 Base64 编码,不是加密。任何人都能解码看到内容,所以不要放密码等敏感信息。


Signature

用来验证 token 未被篡改。生成方式:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

若使用 RSA(如 RS256),则用私钥签名、公钥验证。签名确保:如果有人改了 Header 或 Payload,验证时会失败。


结构示意

┌─────────────────────────────────────────────────────────────┐
│                         JWT 字符串                           │
├──────────────┬──────────────┬───────────────────────────────┤
│    Header    │   Payload    │         Signature             │
│  (Base64URL) │  (Base64URL) │       (Base64URL)             │
├──────────────┼──────────────┼───────────────────────────────┤
│ alg, typ     │ sub, exp,    │ HMAC/RSA 对前两段的签名        │
│              │ 自定义字段    │                               │
└──────────────┴──────────────┴───────────────────────────────┘

验证流程

  1. . 拆成三段
  2. 用同样算法和密钥,对 Header.Payload 重新计算签名
  3. 与第三段比对;一致则未被篡改
  4. 检查 expnbf 等时间相关声明

验签由服务端完成(例如 Supabase 的 PostgREST 用项目 JWT Secret 校验)。客户端持有 token,但不能伪造合法签名。


对比 Session

特性 JWT Session
状态 无状态(服务端可不存) 有状态(服务端要存 session)
体积 较大(含 claims) 较小(通常只有 session ID)
撤销 较难(过期前难以作废) 较易(删 session 即可)
内容 可携带用户信息 用户信息在服务端

在 Supabase 中的位置

JWT 在 Supabase 里承担「携带用户身份」的角色,但不等于数据库权限本身:

阶段 组件 JWT 的作用
登录 Auth 服务(GoTrue) 校验凭据后签发 JWT
查改数据 PostgREST 验签 JWT,把 sub 等写入数据库会话
行级过滤 PostgreSQL RLS 通过 auth.uid() 读会话中的 sub,与表数据比对

登录与数据请求是两条路径:只有登录/refresh 才走 Auth 服务;日常 supabase.from(...).select() 把 JWT 直接带给 PostgREST。

更完整的协作链路见:Supabase RLS 原理与协作


小结

  1. JWT = Header + Payload + Signature,用 . 连接。
  2. Payload 可解码但不可篡改,安全靠签名与 exp 等声明。
  3. sub 是最常用的用户标识 claim;Supabase 用它对应 auth.users.id
  4. 验签在服务端;RLS 只读取验签后注入会话的 claim,不重复验签。