JWT验证

Session

传统 Session 验证方式

在传统的 Session 验证模式中,用户登录成功后,服务器会创建一个会话(Session),并生成一个唯一的 SessionID。这个 SessionID 类似于一个“身份证号”,会被保存在客户端的 Cookie 中。之后,每次用户请求授权页面时,浏览器会自动将这个 SessionID 发送到服务器。服务器会根据这个 ID 查询并验证对应的用户信息。

传统 Session 模式的问题:

  1. 存储压力大:服务器需要维护大量的会话数据,当用户量很大时,会对服务器的存储资源产生压力。
  2. 跨域复杂: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):用户 ID
    • exp(expiration time):过期时间
    • iat(issued at):签发时间
    • iss(issuer):签发者
  • Signature:签名部分是对前两部分数据进行加密的结果,用来验证数据的完整性。签名使用的密钥(Secret)是服务器端保存的,不会暴露给客户端。

JWT 生成流程

  1. 用户登录:用户在登录页面输入用户名和密码,服务器会验证这些凭证是否正确。
  2. 生成 Token:服务器验证成功后,会根据用户信息生成一个 JWT。具体步骤如下:
    • 将用户信息(如 user-id)和一些声明信息(如过期时间、签发者)放入 Payload 部分。
    • 头部(Header)声明签名算法(如 HMAC-SHA256)。
    • 使用服务器的密钥(Secret)通过声明的算法对头部和载荷进行加密,生成签名部分。
    • 最后将这三部分拼接成一个 JWT 字符串,并返回给客户端。

例如,生成的 JWT 字符串可能如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvbiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

这个字符串包含了三部分:头部(第一段)、载荷(第二段)和签名(第三段)。

JWT 的验证过程

当用户需要访问授权页面时,客户端会将 JWT 附带在请求的 Authorization 头中发送到服务器,形式类似:

Authorization: Bearer <JWT>

服务器在接收到请求后,会按照以下步骤验证 Token:

  1. 解析 Token:将收到的 JWT 字符串解码,分为 HeaderPayloadSignature 三部分。
  2. 验证签名:服务器根据 Header 中声明的加密算法和预先保存的密钥,重新对 HeaderPayload 进行加密,生成新的签名。
  3. 签名比对:将生成的签名与 Token 中的签名进行比对。如果一致,则说明 Token 没有被篡改,并且验证通过。
  4. 检查过期时间:验证通过后,还需要检查 exp 声明(过期时间),如果当前时间超过了这个时间,则 Token 失效。

Access-Token 和 Refresh-Token

为了提高安全性和灵活性,JWT 通常会引入 Access-TokenRefresh-Token

Access-Token(访问令牌):

  • 主要作用Access-Token 是用来验证用户身份的令牌。它包含了用户的基本信息和权限,通常具有较短的有效期(如 5 分钟到 30 分钟)。服务器在验证请求时,会使用这个 Access-Token 来确认用户的身份。
  • 特点:因为 Access-Token 的有效期较短,即使它被窃取,攻击者可以利用的时间也有限。它在短时间内反复使用时更加安全和高效。

Refresh-Token(刷新令牌):

  • 主要作用Refresh-Token 主要用于获取新的 Access-Token。它在用户登录时由服务器一并签发,并且具有较长的有效期(可能是几小时、几天,甚至更长)。
  • 特点Refresh-Token 通常不会像 Access-Token 那样频繁传递,它只在 Access-Token 过期时才使用,用于向服务器请求新的 Access-TokenRefresh-Token 的生成和签发更加严格,可以设置为仅在特定 IP 地址或设备上有效。

双 Token 机制及其安全性

Token 轮换机制

JWT 通常采用 Access-TokenRefresh-Token 的双 Token 机制来降低用户端 Token 被窃取后的风险。它的具体工作流程如下:

  1. 用户登录:用户通过用户名和密码登录,服务器验证成功后,会签发一个短期有效的 Access-Token 和一个长期有效的 Refresh-Token。这两个令牌会同时返回给用户,用户需要安全地存储它们。
  2. 访问受保护资源:在访问受保护的资源时,用户每次请求都会携带 Access-Token,服务器验证 Access-Token 是否有效。如果有效,则允许访问。
  3. Access-Token 过期:由于 Access-Token 的有效期较短,当它过期后,用户的请求将被服务器拒绝(返回 401 未授权状态)。
  4. 使用 Refresh-Token 获取新的 Access-Token:用户在 Access-Token 过期后,可以使用 Refresh-Token 向服务器发送请求,服务器会验证 Refresh-Token 是否有效。如果验证成功,服务器将生成一个新的 Access-Token 并返回给用户。
  5. 更新 Refresh-Token:为进一步提升安全性,可以在生成新 Access-Token 时,更新 Refresh-Token,以防止 Refresh-Token 长期被窃取带来的风险。
防止 Token 窃取的措施
  1. 缩短 Access-Token 的有效期:通过将 Access-Token 的有效期设定得较短,即使 Token 被窃取,攻击者也只能在有限时间内进行操作。
  2. 限制 Refresh-Token 的使用Refresh-Token 可以设置为只能在特定的 IP、设备或时间段内使用,防止跨设备的非法使用。
  3. Token 黑名单机制:服务器可以维护一个 Token 黑名单,当用户主动注销或检测到异常行为时,可以将相关的 Refresh-Token 列入黑名单,拒绝所有使用该 Token 的请求。
  4. HTTPS 传输:确保所有 Token 的传输过程都在安全的 HTTPS 通道中,避免中间人攻击。
  5. 安全存储:客户端需要妥善存储 Access-TokenRefresh-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请求库)