← 返回题目列表

Node.js 接口鉴权中 Session 和 JWT 有什么区别?

高频 中等 第 3 / 27 题 更新于 2026/07/27
Node.jsJWTSession鉴权

简化版

Session 是服务端保存登录状态,客户端只保存 session id;JWT 是客户端保存带签名的 token,服务端校验签名和过期时间。Session 易于主动失效,JWT 更适合无状态扩展,但撤销和泄漏控制更麻烦。

详细版

Session 流程:

  1. 用户登录成功。
  2. 服务端保存 session。
  3. 客户端 cookie 保存 session id。
  4. 后续请求带 cookie,服务端查 session。

JWT 流程:

  1. 用户登录成功。
  2. 服务端签发 token。
  3. 客户端保存 token。
  4. 后续请求带 token,服务端验签。

JWT 不等于加密,默认只是 Base64URL 编码加签名,payload 不要放敏感明文。

完整版教学

一、Session 的特点

Session 状态在服务端,服务端可以随时删除 session,让用户立刻下线。缺点是多实例部署时要共享 session,通常用 Redis。

Session 很适合传统 Web、管理后台、需要强控制在线状态的系统。

二、JWT 的特点

JWT 包含 header、payload、signature。服务端用密钥验签,确认 token 没被篡改。

它的优势是服务端不必每次查存储,天然适合分布式服务。但一旦 token 签发出去,在过期前通常仍然有效,除非引入黑名单或版本号机制。

三、安全注意点

JWT payload 只是编码,不是加密。不要放密码、身份证号、密钥等敏感信息。

token 存储也要谨慎:localStorage 易受 XSS 影响;cookie 要设置 HttpOnly、Secure、SameSite,防止脚本读取和跨站风险。

四、面试追问与工程落地

常见追问是“JWT 如何主动失效”。可以缩短 access token 有效期,配合 refresh token;或者服务端维护黑名单、用户 tokenVersion、密钥轮换。代价是重新引入服务端状态。

工程选型不要盲目说 JWT 更先进。后台管理系统用 Session 很正常;开放 API、微服务网关、移动端登录常用 JWT。关键看撤销需求、部署形态和安全边界。

五、把存储、校验和撤销成本放在一起比较

Session cookie 只携带一个高熵随机 id,服务端根据 id 查找状态;JWT 常把 subaudexp 等 claims 放进令牌,资源服务器验签后决定是否接受。签名证明内容未被未授权修改,不证明持有者就是原用户,也不为 payload 提供保密性。

Session:Cookie(sessionId) → 服务端存储查询 → 得到用户状态
JWT:Bearer token → 验算法/签名/iss/aud/exp/nbf → 得到 claims

假设有 10 万在线会话,每条序列化状态约 1 KB,服务端会话数据约 100 MB,另有索引和 Redis 开销;JWT 可省掉每次会话查询,却会让每个请求多携带数百字节令牌。二者是在存储查询、网络带宽和撤销能力之间换成本,不存在天然“更高性能”的结论。

维度Session自包含 JWT access token
登录状态位置服务端存储token claims
每次校验查 session + 校验 cookie本地验签 + claims 校验
主动撤销删除 session 即可需短有效期、黑名单或版本号
多实例共享存储或粘性会话共享验签密钥/公钥
泄漏影响session 生命周期内token 到期或被撤销前

六、令牌生命周期与浏览器威胁模型

常见设计是短期 access token 配合长期 refresh token,例如 access token 15 分钟、refresh token 7 天并轮换。短期令牌缩小泄漏窗口,refresh token 轮换可以检测旧令牌重放;但服务端必须保存会话族、撤销状态或 tokenVersion,于是系统重新引入了有限状态。

放在 HttpOnly、Secure、SameSite cookie 中可以降低脚本直接读取令牌的风险,但 cookie 会自动随请求发送,仍需评估 CSRF;放 localStorage 不会自动产生 CSRF,却会直接暴露给成功执行的 XSS。存储方案必须与 CSP、CSRF token、SameSite 和业务客户端类型一起设计。

校验 JWT 时要固定允许的算法,并验证 issuer、audience、expiration、not-before 等业务所需 claims;不能只做 Base64 解码或只看签名。密钥轮换应使用 kid 选择受信任密钥,但不能让攻击者通过任意路径控制密钥来源。

安全锚点:JWT 解决的是可验证 claims 的传递,不解决令牌盗用、权限实时变更和主动撤销。

刷新令牌轮换流程

刷新端点不能只验证签名后无条件发新令牌,推荐把每个 refresh token 关联一个服务端可撤销标识,并执行轮换:

  1. 校验签名、issaudexp 与允许的算法。
  2. 查询该 token 标识是否已撤销、是否属于当前会话族。
  3. 原子地废弃旧 refresh token,并签发新的 access/refresh 组合。
  4. 若已废弃的 refresh token 再次出现,视为可能被盗,撤销整条会话族。
  5. 密码修改、账号封禁或主动退出时,撤销对应会话而不是等待自然过期。

这种设计增加了一次服务端状态查询,却把“长效凭证被复制后可一直重放”的窗口收窄。面试中应明确:短 access token 偏向无状态校验,refresh token 的轮换与撤销本来就允许引入状态。

七、常见误区与追问

  • 误区:JWT payload 有签名,所以内容是加密的。 常见 JWS 只提供完整性,Base64URL 内容可以直接解码阅读。
  • 误区:使用 JWT 就能做到完全无状态。 刷新令牌轮换、注销、黑名单和权限实时变更通常仍需要状态。
  • 误区:JWT 天然比 Session 更安全。 安全取决于传输、存储、过期、撤销和 claims 校验,两者都可能被盗用。
  • 追问:为什么验签后还要检查 aud 和 iss? 签名有效只说明由某密钥签发,不能证明它面向当前服务或来自预期签发者。
  • 追问:用户修改密码后怎样让旧 token 失效? 可增加 tokenVersion、撤销会话族或缩短 access token 并拒绝旧 refresh token。
  • 追问:Cookie 存 JWT 是否就不会有 CSRF? 不会,自动携带凭证仍需 SameSite 和必要的 CSRF 防护。
  • 追问:Session 多实例一定要粘性会话吗? 不一定,更常见是把 session 放 Redis 等共享存储,任意实例都可查询。

八、加强记忆

Session 是“状态在服务端”,JWT 是“状态在 token 里”。Session 好撤销,JWT 好扩展;JWT 有签名但不是加密。