JWT验证
Session
传统 Session 验证方式
在传统的 Session 验证模式中,用户登录成功后,服务器会创建一个会话(Session),并生成一个唯一的 SessionID。这个 SessionID 类似于一个“身份证号”,会被保存在客户端的
Cookie 中。之后,每次用户请求授权页面时,浏览器会自动将这个 SessionID 发送到服务器。服务器会根据这个
ID 查询并验证对应的用户信息。
传统 Session 模式的问题:
- 存储压力大:服务器需要维护大量的会话数据,当用户量很大时,会对服务器的存储资源产生压力。
- 跨域复杂:SessionID 通常依赖于 Cookie,而 Cookie 的跨域传输有严格的安全策略,这给分布式和跨域场景的应用增加了复杂性。
JWT
JWT(JSON Web Token)的原理
JWT 解决了传统 Session 跨域验证的困难,并减少了服务器的存储压力。
它的原理是通过生成一个自包含的 Token(令牌),其中包含了用户的基本信息,并通过数字签名来保证 Token 的完整性和不可篡改性。与传统 Session 不同,JWT 是无状态的,不需要服务器存储会话信息。
JWT 的组成
JWT 由三部分组成,分别为 Header(头部)、Payload(载荷)、Signature(签名)。这三部分通过 . 连接起来形成一个完整的
JWT 字符串。
- Header:头部一般会声明使用的签名算法,比如
HMAC-SHA256。 - Payload:载荷部分包含用户的基本信息和一些声明(Claims)。这部分内容是明文的,因此不应包含敏感信息。常见的
Claims 有:
sub(subject):用户 IDexp(expiration time):过期时间iat(issued at):签发时间iss(issuer):签发者
- Signature:签名部分是对前两部分数据进行加密的结果,用来验证数据的完整性。签名使用的密钥(Secret)是服务器端保存的,不会暴露给客户端。
JWT 生成流程
- 用户登录:用户在登录页面输入用户名和密码,服务器会验证这些凭证是否正确。
- 生成 Token:服务器验证成功后,会根据用户信息生成一个 JWT。具体步骤如下:
- 将用户信息(如 user-id)和一些声明信息(如过期时间、签发者)放入
Payload部分。 - 头部(Header)声明签名算法(如
HMAC-SHA256)。 - 使用服务器的密钥(Secret)通过声明的算法对头部和载荷进行加密,生成签名部分。
- 最后将这三部分拼接成一个 JWT 字符串,并返回给客户端。
- 将用户信息(如 user-id)和一些声明信息(如过期时间、签发者)放入
例如,生成的 JWT 字符串可能如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvbiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这个字符串包含了三部分:头部(第一段)、载荷(第二段)和签名(第三段)。
JWT 的验证过程
当用户需要访问授权页面时,客户端会将 JWT 附带在请求的 Authorization 头中发送到服务器,形式类似:
Authorization: Bearer <JWT>
服务器在接收到请求后,会按照以下步骤验证 Token:
- 解析 Token:将收到的 JWT 字符串解码,分为
Header、Payload和Signature三部分。 - 验证签名:服务器根据
Header中声明的加密算法和预先保存的密钥,重新对Header和Payload进行加密,生成新的签名。 - 签名比对:将生成的签名与 Token 中的签名进行比对。如果一致,则说明 Token 没有被篡改,并且验证通过。
- 检查过期时间:验证通过后,还需要检查
exp声明(过期时间),如果当前时间超过了这个时间,则 Token 失效。
Access-Token 和 Refresh-Token
为了提高安全性和灵活性,JWT 通常会引入 Access-Token 和 Refresh-Token:
Access-Token(访问令牌):
- 主要作用:
Access-Token是用来验证用户身份的令牌。它包含了用户的基本信息和权限,通常具有较短的有效期(如 5 分钟到 30 分钟)。服务器在验证请求时,会使用这个Access-Token来确认用户的身份。 - 特点:因为
Access-Token的有效期较短,即使它被窃取,攻击者可以利用的时间也有限。它在短时间内反复使用时更加安全和高效。
Refresh-Token(刷新令牌):
- 主要作用:
Refresh-Token主要用于获取新的Access-Token。它在用户登录时由服务器一并签发,并且具有较长的有效期(可能是几小时、几天,甚至更长)。 - 特点:
Refresh-Token通常不会像Access-Token那样频繁传递,它只在Access-Token过期时才使用,用于向服务器请求新的Access-Token。Refresh-Token的生成和签发更加严格,可以设置为仅在特定 IP 地址或设备上有效。
双 Token 机制及其安全性
Token 轮换机制:
JWT 通常采用 Access-Token 和 Refresh-Token 的双 Token 机制来降低用户端
Token 被窃取后的风险。它的具体工作流程如下:
- 用户登录:用户通过用户名和密码登录,服务器验证成功后,会签发一个短期有效的
Access-Token和一个长期有效的Refresh-Token。这两个令牌会同时返回给用户,用户需要安全地存储它们。 - 访问受保护资源:在访问受保护的资源时,用户每次请求都会携带
Access-Token,服务器验证Access-Token是否有效。如果有效,则允许访问。 Access-Token过期:由于Access-Token的有效期较短,当它过期后,用户的请求将被服务器拒绝(返回 401 未授权状态)。- 使用
Refresh-Token获取新的Access-Token:用户在Access-Token过期后,可以使用Refresh-Token向服务器发送请求,服务器会验证Refresh-Token是否有效。如果验证成功,服务器将生成一个新的Access-Token并返回给用户。 - 更新
Refresh-Token:为进一步提升安全性,可以在生成新Access-Token时,更新Refresh-Token,以防止Refresh-Token长期被窃取带来的风险。
防止 Token 窃取的措施:
- 缩短
Access-Token的有效期:通过将Access-Token的有效期设定得较短,即使 Token 被窃取,攻击者也只能在有限时间内进行操作。 - 限制
Refresh-Token的使用:Refresh-Token可以设置为只能在特定的 IP、设备或时间段内使用,防止跨设备的非法使用。 - Token 黑名单机制:服务器可以维护一个 Token 黑名单,当用户主动注销或检测到异常行为时,可以将相关的
Refresh-Token列入黑名单,拒绝所有使用该 Token 的请求。 - HTTPS 传输:确保所有 Token 的传输过程都在安全的 HTTPS 通道中,避免中间人攻击。
- 安全存储:客户端需要妥善存储
Access-Token和Refresh-Token,避免在不安全的环境中暴露。
JWT 及双 Token 机制的优势与适用场景
JWT 的优缺点
优点:
- 无状态:JWT 不需要服务器存储会话数据,验证过程完全基于 Token 自身,减轻了服务器的存储负担。
- 跨域便利:因为 JWT 仅需要附带在请求头中,不依赖 Cookie 的跨域机制,特别适合前后端分离的应用场景。
- 安全性:通过数字签名保证了 Token 的完整性,如果 Token 被篡改,验证签名时就会失败。
缺点:
- Payload 明文存储:JWT 的载荷部分是明文存储的,任何人都可以解码查看其中的内容,因此不要将敏感信息放入
Payload。 - Token 长度较大:与 SessionID 相比,JWT 的字符串较长,占用更多的带宽。
- 无法主动失效:一旦 Token 发放出去,就无法在不修改密钥的情况下主动使其失效(除非通过 Redis 等方式进行 Token 黑名单控制)。
使用场景:
- 单点登录(SSO):因为 JWT 可以在多个服务器之间共享,适用于多服务或多应用的统一身份验证。
- 移动应用:JWT 不依赖浏览器的 Cookie,适合移动端使用。
- 微服务架构:每个微服务都可以验证 JWT,不需要单独的认证中心。
JWT 是一种无状态的、基于令牌的验证方式,适用于分布式架构、微服务和跨域应用场景。相比传统的 Session 验证方式,JWT 提高了跨域访问的便利性,并减少了服务器的存储压力。尽管有安全性和失效管理方面的不足,但通过合理的设计和使用,它依然是现代 Web 应用中广泛采用的认证方案之一。
双 Token 机制优势:
- 减少频繁的身份验证:用户在短期内无需反复登录,提高了用户体验。
- 增强安全性:即使
Access-Token被窃取,攻击者的有效时间也很短;而Refresh-Token的使用相对较少,可以通过更严格的限制来进一步保护。 - 提高灵活性:
Refresh-Token的长效性允许服务器根据需要自动延长用户的会话,而无需用户重新登录。
总结来说,Access-Token 用于频繁的身份验证,而 Refresh-Token 则用于在 Access-Token 过期时获取新的令牌。通过双
Token 机制,可以降低 Token 被窃取带来的风险,并提供更加灵活和安全的验证方式。
项目分区导航: Postman ⬅️ | 03-JWT验证 | ➡️ 前端请求工具(HTTP请求库)
💬 评论