题目
如何安全地在浏览器端存储和传输JWT令牌?
信息
- 类型:问答
- 难度:⭐⭐
考点
JWT安全存储,传输安全措施,CSRF/XSS防御
快速回答
安全处理JWT的核心要点:
- 存储选择:优先使用HttpOnly的Cookie存储,避免localStorage/sessionStorage
- 传输安全:始终通过HTTPS传输,设置Secure和SameSite属性
- 令牌设计:使用短期有效的access token配合refresh token机制
- 防御措施:添加CSRF Token防御跨站请求伪造
- 敏感操作:关键操作要求重新认证
一、原理说明
JWT(JSON Web Token)是无状态认证的核心机制,包含Header、Payload、Signature三部分。浏览器端安全风险主要来自:
- XSS攻击:恶意脚本窃取存储的令牌
- CSRF攻击:诱导用户发送非法请求
- 中间人攻击:未加密通道传输令牌
二、最佳实践与代码示例
1. 安全存储方案
// 后端设置HttpOnly Cookie(Node.js示例)
res.cookie('token', accessToken, {
httpOnly: true, // 阻止JavaScript访问
secure: true, // 仅通过HTTPS传输
sameSite: 'Strict',// 阻止跨站发送
maxAge: 15 * 60 * 1000 // 15分钟有效期
});替代方案:若必须使用localStorage:
// 前端加密存储(AES示例)
const encryptedToken = CryptoJS.AES.encrypt(
token,
'动态获取的秘钥'
).toString();
localStorage.setItem('encToken', encryptedToken);2. 安全传输机制
- 所有API请求自动携带Cookie(浏览器默认行为)
- 敏感请求附加CSRF Token:
<!-- 前端嵌入CSRF Token --> <meta name="csrf-token" content="{{csrfToken}}"> <!-- Axios拦截器示例 --> axios.defaults.headers.common['X-CSRF-Token'] = getCSRFToken();
3. 令牌生命周期管理
// 双令牌机制示例
{
"access_token": "eyJ...", // 短期令牌(15分钟)
"refresh_token": "eyJ..." // 长期令牌(7天,存储于HttpOnly Cookie)
}三、常见错误
- 致命错误:localStorage存储+无HTTPS传输
- 配置缺陷:未设置SameSite属性导致CSRF风险
- 过度信任:使用JWT payload存储敏感数据(未加密)
- 长效令牌:access token有效期超过30分钟
四、扩展知识
- 令牌吊销:通过黑名单或refresh token轮转实现
- 增强措施:
- 指纹绑定:将用户设备指纹加入JWT签名
- 令牌分割:access token拆分为两个部分存储
- 新标准:Backend-for-Frontend模式替代直接存储
五、防御方案对比
| 方案 | 防XSS | 防CSRF | 实施复杂度 |
|---|---|---|---|
| HttpOnly Cookie | ✓ | 需配合SameSite | 低 |
| localStorage + CSRF Token | ✗ | ✓ | 中 |
| 内存存储(单页应用) | ✓ | 需额外处理 | 高 |