The Sejolyn Memo

Back

应用场景#

互联网服务中最常见的功能便是用户认证,比如登陆了某个网站后下次就可以自动登录。

由于 HTTP 是无状态协议,因此使用 cookie 来进行用户认证。

1、用户向服务器发送用户名和密码。

2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

3、服务器向用户返回一个 session_id,写入用户的 Cookie。

4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。
plaintext

但是问题在于,这里的 session 信息保存在哪里?

  1. 保存在持久层(数据库),服务收到请求后,向持久层请求数据。

    • 缺点:工程量大
  2. 保存在客户端,每次请求时发给 session

JWT,即 Json Web Token 就是第二种方案。

现实应用#

传统的导入和配置不再赘述,主要讲一些扩展。

缺陷#

如果黑客截获了 JWT,那么其就可以在令牌过期前冒充用户,进行一切合法的操作

这也是所有基于 Token 机制所面临的共同安全挑战。

为什么 JWT 泄漏后可以被冒充?

  1. 无状态性

    • JWT 被生成后,后端服务器不会在内存或 Redis 中存储其状态
    • 后端只通过 Token 的签名来验证其是否有效、过期,而无法知道其是否泄漏或被调用
  2. 自包含性

    • JWT 内部包含了用户信息(比如苍穹外卖中的 user_id
    • 黑客只需要将 JWT 包含在 HTTP 请求头中,拦截器看到 Token 是合法的,就会认为这个请求是用户 user_id 发出的

对于基于 Session 的认证,服务器会在内存或 Redis 中存储 Session ID。如果用户密码泄漏或检测到异地登录,服务器就可以直接删除这个 Session ID,用户就会立即掉线。

但 JWT 是无状态的,即:

  • 无法注销:JWT 的注销只是前端删除了本地存储的 Token。Token 本身依然有效,直到过期
  • 无法吊销:在 Token 有效期内,即使服务器发现该 Token 被盗,也无法立刻使其实效

3.2 补救#

对于 Web 应用,可以采取以下几种措施来降低 JWT 泄漏的风险:

  1. 设置极短的有效期:如果用户体验要求高,可以引入 Refresh Token 机制

    • Access Token 设置 1 小时有效

    • 额外签发一个 Refresh Token,设置 7 天有效,用于在 Access Token 过期后安静的换取新的 Access Token,减少用户登录的次数

  2. 实现 Token 黑名单机制

    • 做法:将指定用户的 JWT ID 存入 Redis 黑名单中,并设置黑名单过期时间与 JWT 有效期一致

    • 校验流程:拦截器在校验 JWT 签名和有效期时,会额外查询其 ID 是否包含在 Redis 黑名单中

    • 如果 Token 被加入黑名单,其就无法在请求服务

  3. 增强传输安全性(HTTPS)

    • 使用更安全的 HTTPS 进行加密传输,降低了 JWT 被截获的风险
「苍穹外卖」复盘:JWT
https://sejolyn.fyi/blog/sky-take-out/jwt
Author Sejolyn
Published at December 19, 2025
Comment seems to stuck. Try to refresh?✨