网页token介绍(web token、web认证、web令牌、网页令牌)(JWT格式:JSON Web Token,头部Header、载荷Payload、签名Signature)
文章目录
- Web Token 详解:从认证机制演变到实现原理
- 认证机制的演变史
- 传统认证方式的局限
- - 服务器负载增加
- - 扩展性受限
- - 跨域应用困难
- - CSRF攻击风险高
- 无状态认证的崛起
- Web Token 核心概念
- 什么是Web Token
- Token家族成员
- - **JWT (JSON Web Token)**: 最流行的实现
- - **SWT (Simple Web Token)**: 微软早期推出的简化版本
- - **SAML Token**: 企业级身份联盟标准
- JWT深度剖析
- 结构组成()JWT由三部分构成,以点(.)分隔)
- Header(头部)
- Payload(载荷)
- Signature(签名)
- 认证流程详解
- 基本工作流程
- 1. 用户登录提交凭证
- 2. 服务器验证凭证
- 3. 服务器生成JWT
- 4. 返回JWT给客户端
- 5. 客户端存储JWT
- 6. 后续请求附带JWT
- 7. 服务器验证JWT有效性
- 实现案例
- Node.js实现示例
- 前端使用示例
- 安全考量
- 常见安全问题
- - **Token泄露**: 使用HTTPS,避免localStorage存储
- - **重放攻击**: 添加适当的过期时间
- - **弱签名密钥**: 使用强密钥,定期轮换
- - **敏感数据暴露**: 避免在payload中存放敏感信息
- 最佳实践
- - 合理设置过期时间
- - 实现刷新令牌机制
- - 使用HTTPS传输
- - 限制令牌作用域
- - 考虑使用黑名单机制处理注销
- 基本原理
- 工作原理
- 技术实现
- 存储方案选择
- 优化策略
- 性能与存储优化
- 分布式系统考虑
- 实践建议
- 进阶话题
- 无状态与有状态JWT
- 微服务架构中的令牌传递
- 未来发展
Web Token 详解:从认证机制演变到实现原理
认证机制的演变史
传统认证方式的局限
传统Web应用程序采用基于会话的认证方式,服务器需维护会话状态,存在以下问题:
- 服务器负载增加
每个用户会话都需要在服务器内存中占用空间,随着并发用户增加,服务器资源消耗迅速增长。大型应用可能需要维护数十万甚至数百万会话,严重影响服务器性能。
- 扩展性受限
在分布式系统和集群环境下,会话状态难以共享。实现水平扩展时,需要采用会话复制、粘性会话或中央会话存储等机制,这些方案要么增加系统复杂度,要么引入单点故障风险,限制了系统的弹性扩展能力。
- 跨域应用困难
基于Cookie的会话受浏览器同源策略限制,跨域共享认证状态困难。在现代应用架构中,前后端分离、多端应用共存场景下,传统会话机制需要额外配置CORS、共享Cookie等复杂设置,增加了开发和维护成本。
- CSRF攻击风险高
传统会话认证依赖Cookie自动发送机制,容易遭受跨站请求伪造攻击。攻击者可以诱导用户访问恶意网站,利用浏览器自动附加的Cookie向受信任站点发起未授权请求,危及用户安全。防御CSRF需实现额外的令牌验证,增加了开发复杂度。
无状态认证的崛起
为解决上述问题,业界开始转向基于令牌的无状态认证机制,Web Token应运而生。
Web Token 核心概念
什么是Web Token
Web Token是一种紧凑、自包含的数据传输方式,可安全地在各方之间传递信息。这些信息经过数字签名,可验证其完整性和真实性。
Token家族成员
- JWT (JSON Web Token): 最流行的实现
- SWT (Simple Web Token): 微软早期推出的简化版本
- SAML Token: 企业级身份联盟标准
JWT深度剖析
结构组成()JWT由三部分构成,以点(.)分隔)
Header.Payload.Signature
Header(头部)
{ "alg": "HS256", "typ": "JWT" }
Payload(载荷)
{ "sub": "1234567890", "name": "张三", "iat": 1516239022, "exp": 1516242622 }
Signature(签名)
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
认证流程详解
基本工作流程
1. 用户登录提交凭证
2. 服务器验证凭证
3. 服务器生成JWT
4. 返回JWT给客户端
5. 客户端存储JWT
6. 后续请求附带JWT
7. 服务器验证JWT有效性
实现案例
Node.js实现示例
const jwt = require('jsonwebtoken'); // 引入JWT库,用于生成和验证令牌 const secret = 'your-secret-key'; // 定义签名密钥,实际应用中应使用环境变量存储 // 生成token函数 function generateToken(user) { return jwt.sign( { id: user.id, role: user.role }, // payload部分,包含用户ID和角色信息 secret, // 使用密钥进行签名 { expiresIn: '2h' } // 设置令牌2小时后过期 ); } // 验证token函数 function verifyToken(token) { try { return jwt.verify(token, secret); // 使用相同密钥验证令牌,成功则返回解码后的payload } catch (err) { return null; // 验证失败(令牌无效、过期或被篡改)返回null } }
前端使用示例
// 存储token到浏览器本地存储 // 注意:在生产环境中考虑使用httpOnly cookie代替localStorage以增强安全性(指使用httpOnly Cookie存储JWT) localStorage.setItem('token', receivedToken); // API请求中使用token进行身份验证 fetch('https://api.example.com/data', { headers: { // 按照Bearer令牌规范添加到Authorization头 'Authorization': `Bearer ${localStorage.getItem('token')}` } })
安全考量
常见安全问题
- Token泄露: 使用HTTPS,避免localStorage存储
- 重放攻击: 添加适当的过期时间
- 弱签名密钥: 使用强密钥,定期轮换
- 敏感数据暴露: 避免在payload中存放敏感信息
最佳实践
- 合理设置过期时间
- 实现刷新令牌机制
- 使用HTTPS传输
- 限制令牌作用域
- 考虑使用黑名单机制处理注销
基本原理
JWT黑名单是解决无状态令牌注销问题的技术方案。由于JWT设计为自包含且无状态,一旦签发就有效,直到过期,这导致传统注销机制失效。
工作原理
- 服务器维护一个已注销但未过期令牌列表
- 用户注销时,将当前令牌加入黑名单
- 每次验证令牌时,先检查其是否在黑名单中
- 黑名单中的令牌被视为无效,即使签名验证通过
技术实现
存储方案选择
// 使用Redis实现JWT黑名单 const redis = require('redis'); const client = redis.createClient(); // 将令牌加入黑名单,过期时间与令牌剩余有效期一致 async function blacklistToken(token) { // 解码JWT获取过期时间(不验证签名) const payload = jwt.decode(token); if (!payload || !payload.exp) return false; // 计算剩余有效期(秒) const expiryTimeInSeconds = payload.exp - Math.floor(Date.now() / 1000); if (expiryTimeInSeconds payload.jti || token}`, expiryTimeInSeconds, '1'); return true; } // 检查令牌是否在黑名单中 async function isTokenBlacklisted(token) { const payload = jwt.decode(token); if (!payload) return true; // 无效令牌视为已黑名单 const blacklisted = await client.get(`bl_${payload.jti || token}`); return !!blacklisted; // 存在返回true,不存在返回false } // 验证令牌(包含黑名单检查) async function verifyToken(token) { try { // 先检查是否在黑名单中 const blacklisted = await isTokenBlacklisted(token); if (blacklisted) return null; // 不在黑名单中,进行正常JWT验证 return jwt.verify(token, secret); } catch (err) { return null; } } // 订阅黑名单更新频道 const subscriber = redis.createClient(); subscriber.subscribe('token_blacklist'); // 监听黑名单更新消息 subscriber.on('message', (channel, message) = { if (channel === 'token_blacklist') { // 可选:维护本地内存缓存以减少Redis查询 localBlacklistCache.add(message); } }); } // 发布黑名单更新 async function blacklistAndPublish(token) { await blacklistToken(token); // 通知所有服务实例更新黑名单 const publisher = redis.createClient(); await publisher.publish('token_blacklist', token); }
实践建议
- 合理设置JWT过期时间:短期令牌(15-30分钟)可减小黑名单规模
- 实现刷新令牌机制:配合刷新令牌使用,主令牌短期过期减轻黑名单压力
- 定期清理:除依赖存储系统自动过期外,定期额外清理确保系统健康
- 监控黑名单规模:建立监控预警,防止黑名单过大影响性能
黑名单机制本质上为无状态JWT添加了有状态的检查层,在安全与性能间取得平衡,适用于对注销及令牌撤销有严格要求的系统。
进阶话题
无状态与有状态JWT
无状态JWT完全依赖令牌本身,有状态JWT则需要服务端维护部分状态,各有利弊。
微服务架构中的令牌传递
微服务环境下,需要考虑令牌传递策略,确保各服务可验证和获取必要信息。
未来发展
随着分布式系统和零信任架构普及,Web Token技术将持续演进,与OIDC、FIDO2等标准进一步融合,提供更安全、便捷的身份认证机制。
(图片来源网络,侵删)(图片来源网络,侵删)(图片来源网络,侵删)