📚 什么是JWT?
JWT (JSON Web Token) 是一个开放标准 (RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。
JWT 结构组成
Header
头部 - 令牌类型 + 签名算法
.
Payload
载荷 - 实际传输的数据
.
Signature
签名 - 验证令牌完整性
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
详细说明
// 1. Header (头部) - 描述令牌的元数据
{
"alg": "HS256", // 签名算法
"typ": "JWT" // 令牌类型
}
// 2. Payload (载荷) - 包含实际要传输的数据 (Claims)
{
"sub": "1234567890", // 主题 (用户ID)
"name": "John Doe", // 用户名
"iat": 1516239022 // 签发时间
}
// 3. Signature (签名) - 确保令牌未被篡改
// HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
🔄 认证流程对比
🍪 传统Session认证
- 1 用户输入账号密码登录
- 2 服务器验证 credentials
- 3 服务器创建Session,存储用户数据
- 4 Session ID 通过 Cookie 返回给客户端
- 5 后续请求携带 Cookie (Session ID)
- 6 服务器根据 Session ID 查询存储的用户信息
🎫 JWT认证
- 1 用户输入账号密码登录
- 2 服务器验证 credentials
- 3 服务器生成JWT (包含用户信息,签名)
- 4 JWT 返回给客户端 (通常放在响应体或Header)
- 5 后续请求在 Authorization Header 中携带JWT
- 6 服务器验证JWT签名,解析用户信息 (无状态)
⚖️ 详细对比分析
| 对比维度 | 传统Session认证 | JWT认证 |
|---|---|---|
| 状态管理 | 服务端存储Session (有状态) | 服务端不存储 (无状态) |
| 存储位置 | Session ID在Cookie,数据在服务器内存/数据库 | 完整Token在客户端 (LocalStorage/Cookie) |
| 扩展性 | 差 - 需要Session共享 (Redis等) | 好 - 天然支持分布式 |
| 跨域支持 | 困难 - Cookie跨域限制 | 容易 - 可放在Authorization Header |
| 移动端支持 | 不方便 - Cookie管理复杂 | 友好 - 纯Token机制 |
| 性能 | 每次请求需要查询Session存储 | 只需验证签名,无需数据库查询 |
| Token大小 | 小 - 只有Session ID | 大 - 包含完整Payload |
| 注销/过期 | 容易 - 删除服务端Session即可 | 困难 - 需要黑名单或短过期时间 |
| 安全性 | 依赖Cookie安全 (HttpOnly, Secure等) | 需要防范XSS (LocalStorage存储时) |
✅ JWT 的优势与劣势
✅ 优势
- 无状态:服务器不需要存储会话信息,易于扩展
- 跨域友好:不依赖Cookie,适合API认证
- 移动端友好:iOS、Android等原生应用易于集成
- 性能好:避免频繁的数据库查询
- 支持签名和加密:保证数据完整性和机密性
- 标准化:RFC标准,有成熟的库支持
⚠️ 劣势与注意事项
- Token体积大:每次请求都携带完整Token,增加带宽消耗
- 无法主动撤销:Token一旦签发,在过期前一直有效 (除非维护黑名单)
- 存储安全风险:放在LocalStorage有XSS风险,放在Cookie需防范CSRF
- 敏感信息泄露:Payload是Base64编码,可被解码 (不能存储敏感信息)
- 过期时间难以控制:需要配合Refresh Token机制
🛠️ 实际使用演示
JWT生成与验证模拟
点击上方按钮查看演示...
代码示例
// Node.js + jsonwebtoken 库示例
const jwt = require('jsonwebtoken');
// 1. 生成JWT
const token = jwt.sign({
userId: '123456',
username: '张三',
role: 'admin'
}, 'your-secret-key', {
expiresIn: '1h' // 1小时过期
});
// 2. 验证JWT
try {
const decoded = jwt.verify(token, 'your-secret-key');
console.log(decoded); // { userId: '123456', username: '张三', ... }
} catch (err) {
console.log('Token无效或已过期');
}
// 3. 客户端存储和使用
// 存储
localStorage.setItem('token', token);
// 请求时携带
fetch('/api/protected', {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('token')
}
});
💡 JWT 最佳实践
安全建议
- ✅ 使用HTTPS传输Token,防止中间人攻击
- ✅ 设置合理的过期时间 (配合Refresh Token)
- ✅ 使用HttpOnly + Secure Cookie存储Token (防XSS)
- ✅ 对敏感操作要求重新认证
- ✅ 实现Token黑名单机制 (用于注销)
- ✅ 使用强密钥,定期更换
- ❌ 不要在Payload中存储敏感信息 (密码等)
- ❌ 不要将Token存储在localStorage (有XSS风险)
Refresh Token 机制
- 1 用户登录,服务器返回 Access Token (短过期,如15分钟) 和 Refresh Token (长过期,如7天)
- 2 客户端使用Access Token访问API
- 3 Access Token过期,客户端使用Refresh Token请求新的Access Token
- 4 服务器验证Refresh Token,签发新的Access Token
- 5 Refresh Token过期,用户需要重新登录