9-2 JWT的工作原理
本节目标
理解 JWT(JSON Web Token)的结构组成、编码原理、核心特点和工作流程,为后续在 NestJS 中实现用户认证授权奠定理论基础。
什么是 JWT
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象的形式安全地传输信息。JWT 的信息经过数字签名,可以验证和信任。
一个 JWT 由三部分组成,用 . 分隔:
xxxxx.yyyyy.zzzzz
| | |
header payload signature
text
JWT 的三部分结构
Header(头部)
Header 通常包含两部分:令牌类型和使用的签名算法。
{
"alg": "HS256",
"typ": "JWT"
}
json
| 字段 | 说明 |
|---|---|
alg | 签名算法,常见值:HS256、RS256、ES256 |
typ | 令牌类型,固定为 JWT |
Payload(载荷)
Payload 包含要传输的实际数据,称为 Claims(声明)。
{
"sub": "2019-10-01",
"name": "brian",
"admin": true,
"iat": 1516239022
}
json
| 字段 | 说明 |
|---|---|
sub | Subject,令牌主体 |
name | 自定义字段:用户名 |
admin | 自定义字段:是否管理员 |
iat | Issued At,签发时间 |
exp | Expiration Time,过期时间(推荐) |
iss | Issuer,签发者 |
注意:Payload 默认只经过 Base64Url 编码,不加密。不要在 Payload 中存放密码等敏感信息。
Signature(签名)
Signature 用于验证消息在传输过程中没有被篡改。
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
text
签名计算过程:
- 将 Header 进行 Base64Url 编码。
- 将 Payload 进行 Base64Url 编码。
- 将两者用
.连接。 - 使用 Header 中指定的算法和 Secret 密钥对连接后的字符串进行签名。
JWT 编码演示
在 jwt.io 网站上可以实时编码和解码 JWT:
输入 Header: {"alg": "HS256", "typ": "JWT"}
输入 Payload: {"sub": "2019-10-01", "name": "brian", "admin": true}
输入 Secret: secret
生成的 JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIyMDE5LTEwLTAxIiwibmFtZSI6ImJyaWFuIiwiYWRtaW4iOnRydWV9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
text
三个部分对应关系:
eyJhbG...XCU6IkpXVCJ9 -> Header(Base64Url 编码)
eyJzdWI...kbWluIjp0cnVlfQ -> Payload(Base64Url 编码)
SflKxw...dQssw5c -> Signature(HMACSHA256 签名)
text
JWT 的核心特点
1. 防 CSRF(跨站请求伪造)
传统 Session/Cookie 模式:
浏览器自动携带 Cookie -> CSRF 攻击可伪造请求
JWT 模式:
Token 存储在 localStorage 或 Cookie 中
通过 Authorization Header 手动携带
不存在浏览器自动携带的问题 -> 天然防 CSRF
text
2. 适合移动端
Session/Cookie:
依赖浏览器 -> 原生 APP 不支持
JWT:
Token 是纯字符串 -> 任何客户端都可使用
移动端 APP、小程序、桌面应用均适用
text
3. 无状态(Stateless)
Session 模式:
服务端存储会话状态 -> 服务器内存/Redis 开销
多服务器需要共享 Session -> 增加复杂度
JWT 模式:
服务端不存储任何会话状态
验证 Token 签名即可确认身份
天然支持水平扩展
text
JWT 工作流程
客户端 服务端
| |
|--- 1. POST /login ----------->|
| { username, password } |
| |
|<-- 2. 返回 JWT Token ---------|
| { token: "eyJhbG..." } |
| |
|--- 3. GET /api/data --------->|
| Authorization: Bearer |
| eyJhbG... |
| |
| |-- 4. 验证签名
| | 用 secret 解密
| | 检查 exp 过期时间
| |
|<-- 5. 返回数据 ---------------|
| { data: [...] } |
text
详细步骤:
- 登录请求:客户端提交用户名和密码。
- Token 签发:服务端验证通过后,使用 Secret 生成 JWT 并返回。
- 携带 Token:客户端在后续请求的
Authorization: Bearer <token>Header 中携带 JWT。 - 验证 Token:服务端使用相同的 Secret 验证签名,解析 Payload 获取用户信息。
- 返回数据:验证通过后返回请求的数据。
安全性讨论
JWT 的局限
JWT 本身不提供加密,只提供签名验证。Token 被截获后,在过期之前攻击者可以冒用身份:
中间人攻击场景:
客户端 --[Token]--> 中间人 --[Token]--> 服务端
|
v
冒用身份访问数据
text
这是因为 JWT 的无状态特性:服务端不记录 Token 与用户的绑定关系。
安全加固方案
| 方案 | 说明 |
|---|---|
| HTTPS / SSL | 加密通信信道,防止中间人截获 Token |
| 短过期时间 | 设置较短的 exp,配合 Refresh Token 机制 |
| HttpOnly Cookie | 存储 Token 时使用 HttpOnly + Secure 属性 |
| IP 绑定 | 在 Payload 中记录 IP,服务端验证请求来源 |
| Token 黑名单 | 将已注销的 Token 加入黑名单(牺牲无状态性) |
核心理念:没有绝对的安全,只有相对的安全。安全强度取决于算法强度、密钥管理、通信加密等多层防护的综合效果。
本节小结
- 理解了 JWT 的三部分结构:Header(算法和类型)、Payload(用户数据)、Signature(签名验证)。
- 掌握了 JWT 的编码原理:Base64Url 编码 + HMACSHA256 签名。
- 了解了 JWT 的三个核心特点:防 CSRF、适合移动端、无状态。
- 理解了 JWT 的完整工作流程:登录签发 -> 携带请求 -> 签名验证。
- 认识到 JWT 的安全局限性,理解 HTTPS 在 JWT 安全中的关键作用。
↑