JWT(JSON Web Token)是一种紧凑的、URL 安全的字符串,用来在各方之间传递声明(claims)。Supabase Auth、OAuth 2.0 等场景都依赖它传递用户身份。
阅读前提
若想流畅阅读本文,建议已具备:
- 了解 JSON 基本语法
- 了解 HTTP 请求头,尤其是
Authorization: Bearer <token> - 区分认证(证明你是谁)与授权(你能做什么)的基本概念
- (可选)了解 Base64 编码——JWT 使用其 URL 安全变体 Base64URL
基本格式
JWT 由 三部分 组成,用点号 . 连接:
Header.Payload.Signature
例如:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
每一部分都是 Base64URL 编码 的 JSON(签名部分除外,它是二进制结果的编码)。
Header
描述 token 的元数据和签名算法,通常是 JSON:
{
"alg": "HS256",
"typ": "JWT"
}
| 字段 | 含义 |
|---|---|
alg |
签名算法,如 HS256、RS256、ES256 |
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 | 唯一标识 |
还可以放 自定义字段,比如 role、email 等。在 Supabase 签发的 JWT 中,sub 通常对应 auth.users.id,role 常为 authenticated 或 anon。
注意: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 对前两段的签名 │
│ │ 自定义字段 │ │
└──────────────┴──────────────┴───────────────────────────────┘
验证流程
- 按
.拆成三段 - 用同样算法和密钥,对
Header.Payload重新计算签名 - 与第三段比对;一致则未被篡改
- 检查
exp、nbf等时间相关声明
验签由服务端完成(例如 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 原理与协作。
小结
- JWT = Header + Payload + Signature,用
.连接。 - Payload 可解码但不可篡改,安全靠签名与
exp等声明。 sub是最常用的用户标识 claim;Supabase 用它对应auth.users.id。- 验签在服务端;RLS 只读取验签后注入会话的 claim,不重复验签。