跳到主内容
d.devtul.fun
EN
安全 · 2026-09-16

什么是 JWT?写给开发者的 JSON Web Token 入门

JSON Web Token 无处不在——登录会话、API 鉴权、单点登录。但出人意料的是,很多开发者把它当成某种 opaque 的魔法。它不魔法。JWT 就是三段用点连起来的 Base64url 文本,把它解出来,就没什么好琢磨的了。

三段结构

一个 JWT 长这样:xxxxx.yyyyy.zzzzz。每段用点分开:

  • header(头部)——关于这个令牌的元信息:用哪种签名算法、用哪个密钥 id。
  • payload(载荷)——声明(claims):这个用户是谁、什么时候过期,以及你想放的任何东西。
  • signature(签名)——对前两段的密码学签名。

把 header 解出来,是类似这样的 JSON:

{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "key-2026-09"
}

payload 里到底装了什么

payload 是你真正关心的那段。一个典型的已解码 payload:

{
  "sub": "user_8821",
  "name": "Ada Lovelace",
  "role": "admin",
  "exp": 1785000000
}

这些字段叫做声明(claims)。其中有几个是预留了特殊含义的:

声明含义
sub主体(subject)——令牌是关于谁的,通常是用户 id
exp过期时间——过了这个时间点令牌作废(Unix 秒)
iat签发时间——令牌什么时候创建的
nbf生效时间——在此之前令牌无效
iss签发者——谁发的这个令牌
aud受众——谁被允许接受它

payload 谁都能读

这是新手最容易搞错的一点。header 和 payload 做的是 Base64url 编码,不是加密。这里没有密钥参与。任何拿到令牌的人,在浏览器控制台里两行就能解出来:

const [, p] = token.split('.');
JSON.parse(atob(p.replace(/-/g,'+').replace(/_/g,'/')));

所以 payload 是一本敞开的书。永远别把密码、信用卡号或者任何敏感信息放进 JWT 的 payload。这个编码的存在只是为了让结构化数据能塞进一个文本令牌,不是为了藏东西。

签名是干什么的

签名是唯一涉及密钥或私钥的那一段。它是针对 header 和 payload 算出来的:

signature = sign(base64url(header) + "." + base64url(payload), secretOrPrivateKey)

它的作用有两层:证明令牌确实出自持有密钥的一方,以及证明 header 和 payload 在传输途中没被改过。如果攻击者把 "role":"user" 改成 "role":"admin",签名就对不上了,服务端会拒绝。

关键点在于:签名提供的是完整性与真实性,不是机密性。它阻止篡改,但不阻止阅读。

HS256 与 RS256 的区别

算法密钥验证方式
HS256一个共享密钥签发和验证都用同一把密钥
RS256公钥/私钥对认证服务用私钥签,其他服务用公钥验证

HS256 更简单——一把密钥,既能签也能验。缺点是任何能验证的人也能伪造,因为他们拿着同一把密钥。RS256 把角色拆开了:认证服务守住私钥,其余每个服务用一把它无法用来签名的公钥去验证。对于"多个服务信任同一个签发方"的场景,RS256 扩展起来更顺。

为什么 JWT 不适合当会话存储

JWT 是无状态的——服务端不需要会话表,因为一切都在令牌里。听起来是个优势,但有个尖锐的副作用:你很难在令牌过期前把它吊销。让用户登出,而他手里那个仍然有效的令牌,会一直能用到 exp 到期。要补这个洞,你最后还是得建一张吊销列表——把原本想省掉的那个状态又加回来了。

对于短生命周期的 API 访问令牌,无状态没问题。但"记住我、在这台设备上待两周"这种需求,服务端会话或者 refresh token 流程通常是更合适的工具。

什么时候不该用 JWT

  • 用户一登出你就必须让令牌立刻失效——用会话。
  • payload 必须保密——JWT 的 payload 天生可读。
  • 你只是想要一个随机的会话 id——直接用不透明的随机令牌,更简单也更短。

安全地调试一个 JWT

永远不要把生产环境的真实令牌粘进某个来路不明的第三方网站。用你信得过的、在本地运行的客户端解码器。本站这个 JWT 解码器 完全跑在你的浏览器里,令牌不会离开你的机器。粘进去,读一下 header 和 payload,确认 exp 和 aud 符合预期即可。

继续阅读