**创建时间:** 2026-03-27
**最后更新:** 2026-03-27
**阅读时间:** 约 15 分钟
---
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为 JSON 对象。这些信息可以被验证和信任,因为它是数字签名的。
---
JWT 由三部分组成,用点(.)分隔:header.payload.signature
JWT 三部分结构
flowchart LR
subgraph JWT["JWT = Header.Payload.Signature"]
H["eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Header (JSON)"]
P["eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik...
Payload (JSON)"]
S["S = HMACSHA256(
base64(H),
secret)
Signature"]
end
H --> P --> S
style H fill:#3498db,color:#fff
style P fill:#9b59b6,color:#fff
style S fill:#e74c3c,color:#fff
头部通常由两部分组成:令牌类型(即 JWT)和所使用的签名算法(如 HMAC SHA256 或 RSA)。
{
"alg": "HS256",
"typ": "JWT"
}
载荷包含声明(claims)。声明是关于实体(通常是用户)和其他数据的声明。有三种类型的声明:
iss(发行人)、exp(过期时间)、sub(主题)、aud(受众){
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
签名用于验证消息在传送过程中未被更改,并且对于使用私钥签名的令牌,还可以验证 JWT 的发送方是它声称的发送方。
签名算法示例(HMAC SHA256):
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
your-256-bit-secret
)
---
┌──────────┐ ┌──────────┐
│ 客户端 │ │ 服务器 │
└────┬─────┘ └────┬─────┘
│ │
│ 1. 登录请求(用户名/密码) │
│ ─────────────────────────────────────> │
│ │
│ │ 2. 验证凭据
│ │ 3. 生成 JWT
│ │
│ 4. 返回 JWT │
│ <───────────────────────────────────── │
│ │
│ 5. 存储 JWT(localStorage/cookie) │
│ │
│ 6. 后续请求携带 JWT │
│ Authorization: Bearer │
│ ─────────────────────────────────────> │
│ │ 7. 验证签名
│ │ 8. 检查过期时间
│ │
│ 9. 返回受保护资源 │
│ <───────────────────────────────────── │
│ │
---
JWT 完整认证流程
sequenceDiagram
participant U as 用户
participant A as 认证服务器
participant R as 资源服务器
U->>A: 登录 (用户名/密码)
A->>U: 颁发 JWT (Access + Refresh)
Note right of U: Access Token (短期, 如15min)
Refresh Token (长期, 如7天)
U->>R: 请求API (Authorization: Bearer )
R->>R: 验证签名 + 检查 exp
alt Token 有效
R->>U: 返回受保护资源
else Token 过期
R-->>U: 401 Unauthorized
U->>A: 用 Refresh Token 申请新 Token
A->>U: 新 Access Token
end
Token 安全最佳实践
flowchart TD
A[安全传输] --> B[使用 HTTPS]
B --> C[Token 存储]
C --> D[HttpOnly Cookie
或加密存储]
D --> E[短期 Access Token]
E --> F[Refresh Token 轮换]
F --> G[Token 吊销机制]
G --> H[防止 XSS/CSRF]
H --> I[Token 大小控制
避免超长 Payload]
style B fill:#e74c3c,color:#fff
style D fill:#e74c3c,color:#fff
style G fill:#e74c3c,color:#fff
| 优势 | 说明 |
|------|------|
| **无状态** | 服务器不需要存储会话信息,适合分布式系统 |
| **跨域支持** | 天然支持跨域认证,适合微服务架构 |
| **自包含** | 令牌包含所有必要信息,减少数据库查询 |
| **性能优秀** | 验证速度快,不需要查询数据库 |
| **标准化** | RFC 7519 标准,有完善的库支持 |
| 劣势 | 说明 |
|------|------|
| **令牌大小** | 比会话 ID 大,增加网络传输开销 |
| **无法撤销** | 令牌签发后无法主动撤销(除非使用黑名单) |
| **安全性** | 令牌泄露后风险较大,需要妥善保管 |
| **数据可见** | 载荷部分可被解码查看,不应存储敏感信息 |
---
始终通过 HTTPS 传输 JWT,防止中间人攻击窃取令牌。
{
"exp": 1516242622, // 过期时间
"iat": 1516239022 // 签发时间
}
建议:
**错误示例:**
{
"sub": "1234567890",
"password": "secret123", // ❌ 绝对不要这样做
"creditCard": "4111-1111-1111-1111" // ❌ 绝对不要这样做
}
**正确示例:**
{
"sub": "1234567890",
"role": "admin",
"permissions": ["read", "write"]
}
// 验证 JWT 时必须检查
签名是否有效
令牌是否过期(exp)
令牌是否尚未生效(nbf)
发行人是否可信(iss)
受众是否正确(aud)
// ❌ 弱密钥
const secret = "secret123";
// ✅ 强密钥(至少 256 位)
const secret = crypto.randomBytes(32).toString('hex');
---
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
// 生成密钥
const secret = crypto.randomBytes(32).toString('hex');
// 生成 JWT
function generateToken(user) {
const payload = {
sub: user.id,
name: user.name,
role: user.role
};
return jwt.sign(payload, secret, {
expiresIn: '2h',
issuer: 'your-app',
audience: 'your-app-users'
});
}
// 验证 JWT
function verifyToken(token) {
try {
const decoded = jwt.verify(token, secret, {
issuer: 'your-app',
audience: 'your-app-users'
});
return { valid: true, payload: decoded };
} catch (error) {
return { valid: false, error: error.message };
}
}
// 使用示例
const user = { id: 1, name: 'John Doe', role: 'admin' };
const token = generateToken(user);
console.log('Token:', token);
const result = verifyToken(token);
console.log('Verification:', result);
import jwt
import datetime
import secrets
生成密钥
secret = secrets.token_hex(32)
生成 JWT
def generate_token(user):
payload = {
'sub': user['id'],
'name': user['name'],
'role': user['role'],
'iat': datetime.datetime.utcnow(),
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2),
'iss': 'your-app',
'aud': 'your-app-users'
}
return jwt.encode(payload, secret, algorithm='HS256')
验证 JWT
def verify_token(token):
try:
payload = jwt.decode(
token,
secret,
algorithms=['HS256'],
issuer='your-app',
audience='your-app-users'
)
return {'valid': True, 'payload': payload}
except jwt.ExpiredSignatureError:
return {'valid': False, 'error': 'Token expired'}
except jwt.InvalidTokenError as e:
return {'valid': False, 'error': str(e)}
使用示例
user = {'id': 1, 'name': 'John Doe', 'role': 'admin'}
token = generate_token(user)
print('Token:', token)
result = verify_token(token)
print('Verification:', result)
---
| 特性 | JWT | Session |
|------|-----|---------|
| 存储位置 | 客户端 | 服务器 |
| 状态 | 无状态 | 有状态 |
| 跨域支持 | 天然支持 | 需要额外配置 |
| 性能 | 高(无需查库) | 中(需要查库) |
| 安全性 | 依赖令牌保护 | 依赖 Session ID 保护 |
| 撤销 | 困难 | 容易 |
| 存储方式 | 优点 | 缺点 |
|----------|------|------|
| localStorage | 简单易用 | 易受 XSS 攻击 |
| sessionStorage | 会话结束自动清除 | 易受 XSS 攻击 |
| Cookie(HttpOnly) | 防 XSS | 需要防 CSRF |
| Cookie(Secure + HttpOnly) | 最安全 | 配置复杂 |
**推荐:** 使用 Secure + HttpOnly + SameSite 的 Cookie 存储
---
---
**标签:** JWT, 身份验证,API 安全,令牌认证
**分类:** 认证协议