忧郁的大能猫
好奇的探索者,理性的思考者,踏实的行动者。
Table of Contents:
“Token机制”通常指的是一种基于令牌的身份验证模式。其中最主流、最典型的实现是 OAuth 2.0 和 OpenID Connect 中使用的 不透明令牌。
核心流程(以OAuth 2.0为例):
1. 登录:用户提供凭证(如用户名密码)给认证服务器。
2. 颁发Token:认证服务器验证通过后,生成一个唯一的、随机的字符串(即Token),例如 a1b2c3d4e5f6g7h8。服务器会将该Token与用户的身份信息(如用户ID、权限范围)的映射关系存储在数据库或缓存(如Redis)中。
3. 使用Token:客户端(如前端App)在后续请求的Header(如 Authorization: Bearer <token>)中携带此Token。
4. 验证Token:资源服务器(如后端API)收到请求后,需要向认证服务器发起查询,或者自己检查数据库/缓存,来验证这个Token是否有效、是否过期、以及对应的用户权限是什么。
5. 返回资源:验证通过后,资源服务器返回请求的数据。
关键特点:
* 不透明:Token本身只是一串无意义的随机字符,不包含任何信息。
* 服务器有状态:服务器必须存储(Stateful)每个Token及其对应的会话信息。这是一种中心化的存储方式。
* 需要查库:每次验证Token的有效性都需要查询数据库或缓存,会带来一定的性能开销和延迟。
* 强控制力:服务器可以随时让某个Token失效(直接从数据库中删除即可),这是其最大优点。
JWT 是 JSON Web Token 的缩写,它是一种开放的标准,定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象。
gwt流程:
- 首次登录
- token = GenerateToken(user.Id, user.Username, user.Password)
- 创建Claims结构体,包含用户信息和加密相关的设置,比如过期事件,token发行方人
- 使用指定的加密密钥进行加密生成token串
- 非首次登录
- 从http头中获取token
- 使用指定的加密密钥对token串进行解密,并还原出Clains结构体
核心流程:
1. 登录:用户提供凭证给认证服务器。
2. 颁发JWT:认证服务器验证通过后,会将用户的身份信息(Claims,载荷)打包到一个JSON结构中,然后用密钥对其进行签名,生成一个JWT。一个典型的JWT看起来像这样:xxxxx.yyyyy.zzzzz(由Header、Payload、Signature三部分组成)。
3. 使用JWT:客户端在后续请求Header中携带此JWT。
4. 验证JWT:资源服务器收到JWT后:
* 检查签名:使用预先约定好的密钥(或公钥)验证签名是否有效,以证明Token未被篡改。
* 检查标准声明:检查有效期(exp)、受众(aud)等是否合法。
* 整个过程不需要查询数据库或认证服务器!
5. 返回资源:验证通过后,资源服务器直接从JWT的Payload中读取用户信息(如用户ID),然后返回数据。
关键特点:
* 自包含:Token本身包含了所有需要的用户信息,不需要在服务器端存储会话状态。
* 无状态:服务器不需要存储JWT本身,只需要验证其签名和声明即可。这是一种去中心化的验证方式。
* 性能好:避免了每次请求都查询数据库的开销,适合分布式微服务架构。
* 控制力弱:由于服务器无状态,无法在JWT自然过期前让其失效(除非引入额外的黑名单机制,但这又违背了无状态的初衷)。
| 特性 | 传统Token (不透明令牌) | JWT (JSON Web Token) |
|---|---|---|
| 含义 | 一个广义概念,指代令牌认证模式 | 一种具体的Token实现标准 |
| 信息存储 | 存储在服务器端的数据库/缓存中 | 自包含在Token本身的Payload中 |
| 服务器状态 | 有状态,需要维护Token会话信息 | 无状态,无需存储Token本身 |
| 验证方式 | 必须查询数据库/认证服务器进行验证 | 本地验证签名和声明,无需查库 |
| 性能 | 每次验证有网络I/O和数据库查询开销 | 验证速度快,无网络开销,适合分布式系统 |
| 失效控制 | 强控制,可从服务器端立即撤销 | 弱控制,在到期前难以主动撤销(需额外手段) |
| 内容 | 随机字符串,不透明 | 编码后的JSON,可解码查看内容(但不防篡改) |
| 主要场景 | 需要强安全控制、可即时撤销会话的场景 | 一次性验证、短期有效、分布式系统的授权 |