【现代网页开发】有JWT的Token为什么还要用Cookie?

核心概念:JWT 是一种“令牌”格式,而不是一种“存储或传输机制”

Cover

JWT 本身只是一种紧凑且自包含的方式,用于在各方之间安全地传输信息。它定义了令牌的结构(Header.Payload.Signature),并包含验证令牌完整性(未被篡改)和真实性(确实由已知方签发)的方法。

JWT 不关心你如何存储或传输它。 令牌本身可以放在:

  • HTTP 请求头 (Authorization: Bearer )

  • URL 查询参数

  • 请求体

  • Cookie

所以我选择把 JWT 放在了 Cookie 里面,通过 res.cookie 的设置,可以很方便地设置 Cookie 自携带,并且可以一定程度避免 XSS 攻击。

res.cookie('authToken', token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 14400000,
    sameSite: 'Lax', // 或 'None'
});

这条代码的作用就是告诉浏览器:“嘿,我这里有一个 authToken 叫这个值,请把它存起来,并在将来发送到 localhost:3000 的请求中。”

  1. 浏览器自动管理 HTTP-only Cookie。
  • 一旦 Cookie 被设置,浏览器会负责在后续发送到同一域 (或兼容域/路径) 的请求中,自动将其包含在 Request Headers 的 Cookie 字段中。你的前端 JavaScript 代码无需手动读取 localStorage 或 sessionStorage 并将其添加到每个请求头中。
  1. 后端通过 cookie-parser 中间件解析这些 Cookie。
  • 当请求到达后端时,cookie-parser 中间件会解析 Request Headers 中的 Cookie 字段,并将这些 Cookie 的键值对填充到 req.cookies 对象中。

    所以,当你在 /login 路由或 authenticateJWT 中间件中执行 const token = req.cookies.authToken; 时,你实际上是在从浏览器自动发送过来的 Cookie 中获取 JWT。


XSS 和 CSRF

业界普遍认为 XSS 攻击的危害性更大,因为它可以做的事情更多(窃取所有可访问的数据,甚至在用户会话中执行任意操作)。因此,很多应用会选择将 Token 存储在 HttpOnly 的 Cookie 中来防御 XSS,然后通过 SameSite 属性(Lax 或 Strict)或配合 CSRF Token 来防御 CSRF。

所以:

在 JWT 的认证体系中:

  • 将 JWT 存储在 localStorage 或 sessionStorage,并通过 Authorization 请求头发送:
    • 优点: 天然防御 CSRF。

    • 缺点: 极易受到 XSS 攻击,因为恶意 JavaScript 可以直接读取 Token。

  • 将 JWT 存储在 HttpOnly 的 Cookie 中:

    • 优点: 有效防御 XSS 攻击(因为 JavaScript 无法访问 HttpOnly Cookie)。

    • 缺点: 易受 CSRF 攻击(如果 SameSite 设置不当或没有其他 CSRF Token 机制),因为浏览器会自动携带 Cookie。


所以,当你回过神的时候,有没有发现,这个博文的封面,其实是 Session Vs Token …


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注