JWT 是什么?JSON Web Token 完整指南

JWT(JSON Web Token)是目前最流行的无状态鉴权方案之一,被广泛用于前后端分离、微服务、移动端 API 鉴权场景。它本质上是一个由三段 Base64URL 编码字符串拼接而成的紧凑型令牌,里面携带了经过签名的"声明(claims)"。本文将带你彻底搞懂 JWT 的结构、原理、常见算法对比、与传统 Session 的区别,以及生产环境必须避开的 4 个安全坑。

一、JWT 的三段式结构

一个 JWT 长这样:header.payload.signature,每段用英文句点 . 分隔。它遵循 RFC 7519 标准,下面分别拆解。

1. Header(头部)

声明算法令牌类型,例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
"alg": "HS256", "typ": "JWT" }

上面这段 JSON 会被 Base64URL 编码(注意是 URL 安全的 Base64,不是普通 Base64,区别见 Base64 编码完全指南),得到:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

2. Payload(负载)

存放实际要传递的"声明"(claims),分为三类

3. Signature(签名)

用于验证 token 在传输中未被篡改。以 HS256 为例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )

签名是整个 JWT 防伪的核心。服务端收到 token 后,用同样的算法和密钥重算签名,对比是否一致。

二、HS256 vs RS256 vs ES256 怎么选?

JWT 的 alg 字段决定签名算法,三种最常见:

算法 类型 密钥 适用场景
HS256对称 HMAC1 个 secret单体应用、内部服务
RS256非对称 RSA私钥签 + 公钥验多服务验证、OAuth 2.0、OIDC
ES256非对称 椭圆曲线私钥签 + 公钥验移动端、短签名、高安全

选型建议:单体后端用 HS256(简单高效);涉及多个下游服务需要验证 token 时用 RS256(公钥可公开分发,避免密钥泄露);对性能和包大小敏感(移动端 IoT)选 ES256,签名更短、安全性更高。

三、完整示例(来自 jwt.io,可解码验证)

下面这个 token 来自 jwt.io 官方文档,结构完整,可以直接粘到任意 JWT 解码器验证:

Header(原文)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
"alg": "HS256", "typ": "JWT" }

Base64URL 编码后:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Payload(原文)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
"sub": "1234567890", "name": "John", "iat": 1516239022 }

Base64URL 编码后:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

完整 JWT(三段拼接)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gIiJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

把这段粘到 JWT 解码工具,Header / Payload / Signature 即可一目了然。

四、JWT vs Session Cookie 核心对比

维度 JWT Session Cookie
状态无状态(stateless)有状态(服务端存 session)
扩展性天然支持分布式需共享存储(Redis 等)
撤销较难(需黑名单或短 exp)简单(删服务端记录)
体积较大(每次请求都带)轻量(只带 cookie ID)
CSRF免疫(用 Authorization header)需 CSRF token

一句话总结:JWT 赢在扩展性和跨域,Session 赢在撤销和体积。现代系统常用"JWT access token + refresh token"组合来取长补短。

五、实战:用户登录鉴权流程

┌──────────┐                          ┌──────────┐                        ┌──────────┐
│  浏览器  │                          │  鉴权服务 │                        │  业务API │
└────┬─────┘                          └────┬─────┘                        └────┬─────┘
     │  ① POST /login (user, pwd)          │                                  │
     │ ────────────────────────────────────▶│                                  │
     │                                      │  ② 校验账号密码                   │
     │                                      │     生成 JWT(HS256, exp=2h)      │
     │  ③ 返回 { token: "eyJhbG..." }      │                                  │
     │ ◀────────────────────────────────────│                                  │
     │                                      │                                  │
     │  ④ GET /api/user                                                          │
     │    Header: Authorization: Bearer eyJhbG...                              │
     │ ─────────────────────────────────────────────────────────────────────────▶│
     │                                      │                                  │ ⑤ 取出 token
     │                                      │                                  │   验签 + 检查 exp
     │                                      │                                  │   从 sub 取 user_id
     │  ⑥ 200 OK { name: "John" }                                                │
     │ ◀─────────────────────────────────────────────────────────────────────────│
     │                                      │                                  │
     │  ⑦ 2h 后 exp 过期,返回 401                                              │
     │     客户端用 refresh token 换新 access token                              │
     │  ⑧ POST /refresh (refresh_token)                                         │
     │ ────────────────────────────────────▶│                                  │
     │  ⑨ 返回新 access token              │                                  │
     │ ◀────────────────────────────────────│                                  │
     └──────────┘                          └──────────┘                        └──────────┘

六、生产环境 4 个真实安全风险

① 不要把 JWT 放在 localStorage
任意 XSS 漏洞都能 localStorage.getItem('token') 拿到 token。推荐用 httpOnly + Secure + SameSite=Strict 的 cookie 存放,JS 根本无法读取,从源头杜绝 XSS 窃取。
② 必须显式校验 alg 字段
历史上出现过 {"alg":"none"} 攻击(攻击者去掉签名强行通过)和算法替换攻击(用公钥当 HMAC 密钥伪造 RS256 token)。服务端必须写死期望算法,不要相信 header 里的 alg。
③ 强制 HTTPS
JWT 在网络上明文传输等于把用户凭证裸奔。一旦被中间人截获,攻击者就能在 token 有效期内冒充用户。HTTPS(含 HSTS)是底线,没有例外。
④ 短 exp + refresh token
access token 过期时间建议 15 分钟 ~ 2 小时,搭配长寿命的 refresh token(存服务端、可主动撤销)。这样即便 access token 泄露,损失也被控制在小窗口内。

七、3 步在线解码你的 JWT

  1. 打开 devstoolbox.net/tools/jwt-decoder.html
  2. 把 JWT 字符串粘到输入框(Header.Payload.Signature)
  3. 即时看到 header / payload 解码结果,全程浏览器本地解码,不会上传到任何服务器,放心用

💡 如果你处理的是带 ? 或特殊字符的 URL,参考 URL 编码完全指南

八、常见问题 FAQ

Q1: JWT 能存敏感数据吗?

绝对不能。Payload 只是 Base64URL 编码,任何拿到 token 的人都能直接解码看到原文,等同于明文。密码、身份证、手机号、银行卡等信息绝对不能放进 payload。

Q2: JWT 怎么撤销?

三种思路:① 短 exp + refresh token(最常用);② 黑名单(把要撤销的 jti 存 Redis,校验前先查);③ 维护一个 版本号 / 密钥轮换 机制强制旧 token 全部失效。

Q3: JWT 和 OAuth 是什么关系?

两者不是同一层概念。OAuth 2.0 是一种授权框架(authorization framework),解决"第三方应用怎么拿到用户授权"的问题;JWT 是一种 token 格式。OAuth 2.0 实际跑起来时,access token 的载体经常就是 JWT(即所谓的 "JWT Bearer Token")。

Q4: JWT 适合做 API 鉴权吗?

非常适合,特别是 stateless REST API 和微服务。但前提是严格遵守上面的 4 个安全实践:短 exp、HTTPS、显式校验 alg、妥善存放 token。

Q5: 各语言怎么选 JWT 库?

九、总结

JWT 不是银弹,但它凭借无状态、跨域、自包含的特性,在现代分布式架构中几乎成了鉴权的事实标准。掌握它的三段式结构、算法选择、与 Session 的差异、以及 4 个安全红线,你就能在面试和生产中游刃有余。

想快速验证一个 JWT 的内容?直接用 DevToolbox JWT 解码器,粘贴即得结果,纯本地处理,绝不上传

📚 相关文章Base64 编码完全指南 · URL 编码完全指南 · 在线 JWT 解码工具