Skip to content
Go back

Cookie、Session、JWT——三种会话机制的选型与实践

Cookie、Session、JWT:你该用哪种?

一句话结论(30s)

Cookie 是「传输载体」、Session 是「服务端存状态」、JWT 是「自包含无状态令牌」,三者不是替代而是互补——因为 Cookie 只负责把凭证带在请求里,Session 和 JWT 才是状态管理策略,现代架构常用「JWT + HttpOnly Cookie + 短有效期 + Refresh Token」兼顾安全与分布式。

核心原理(2min)

底层深入(5-10min)

Cookie:存在客户端的”通行证”

Cookie 是服务器通过 Set-Cookie 响应头命令浏览器存储的一小段数据(最多 4KB),浏览器在后续请求中自动通过 Cookie 头带回。

浏览器                            服务器
  |                                 |
  |←── Set-Cookie: sessionId=abc ──|  服务器: 记住这个凭证
  |                                 |
  |── Cookie: sessionId=abc ──────→|  浏览器: 自动带上

自动携带是 Cookie 最方便也最危险的特点——CSRF 攻击正是利用了这一特性。

思考:为什么「自动携带」既是优点又是危险?因为浏览器在每次请求时无条件带上 Cookie,省去了手动传凭证的麻烦,但也意味着攻击者只要诱导用户在已登录状态下点一个链接,浏览器就会把 Cookie 连同请求发往攻击者指定的站点——CSRF 正是钻了「浏览器替你代劳」的空子,所以才有 SameSite 来限制跨站携带。

安全属性

Session:存在服务端的”状态”

Session 是一种服务端状态存储,客户端的 Cookie 中只存一个 Session ID(随机字符串)。真正的用户数据(登录用户、权限等)存在服务端(内存/Redis/数据库)。

客户端 Cookie: sessionId = "abc123"
服务端 Redis:  "session:abc123" = {userId: 1001, name: "张三", roles: ["admin"]}

优点:敏感数据不暴露在客户端;可主动销毁(删除 Redis 中的 key) 缺点:集群环境下需共享 Session(Redis 集中存储),增加架构复杂度

思考:为什么集群环境下 Session 就成了负担?因为 Session 状态存在服务端,而负载均衡会把请求打到任意一台机器;如果每台机器各存各的 Session,用户下一次请求落到别的机器上就「失忆」了。所以必须把 Session 抽到共享存储(Redis),这等于给无状态的服务集群强行加了一层有状态依赖,架构复杂度随之上升。

JWT:自包含的无状态令牌

JWT(JSON Web Token)是一个自包含的身份令牌,由三部分组成:

Header.Payload.Signature

Header:   {"alg": "HS256", "typ": "JWT"}
Payload:  {"sub": "1001", "name": "张三", "exp": 1234567890, "iat": 1234560000}
Signature: HMAC-SHA256(base64(Header) + "." + base64(Payload), secret)

服务端只验签,不查库,不存状态。任意节点都可以独立验证。JWT 天然支持分布式——每个微服务用同一密钥验签即可,不需要访问共享存储。

优点

缺点

思考:JWT 的「无状态」怎么反而变成了缺点?因为无状态意味着服务端不记录「哪些 Token 已经作废」,签出去的 Token 在有效期内就是「既成事实」。用户改了密码、账号被盗,服务端想立刻踢下线却无从下手,只能靠缩短有效期或维护黑名单来补救——这就是用「零存储」换「灵活性」的代价。

选型指南

场景推荐方案理由
单体应用Session + Redis可主动销毁,管理方便
微服务架构JWT + 短有效期无状态,各服务独立验证
移动端 AppJWT (localStorage)无 Cookie 环境
高安全场景HttpOnly Cookie + Session双重防护 XSS + CSRF
需要立即失效Session服务端删除即可

JWT 泄露怎么办?

JWT 一旦泄露(如 XSS 攻击偷走 localStorage 中的 Token),攻击者可以在有效期内伪装用户。唯一的防线是让 Token 尽快过期

标准做法:

总结

三者不是替代关系,而是互补关系。Cookie 是传输载体,Session 和 JWT 是状态管理策略。现代架构中常用的模式是:JWT + HttpOnly Cookie + 短有效期 + Refresh Token——兼顾安全性和分布式友好性。

章末提问

Q1:Cookie 和 Session 是什么关系?JWT 又是什么?

结论先行:Cookie 是传输载体,Session 和 JWT 是两种不同的状态管理策略。因为 Cookie 只是浏览器自动携带的一小段数据,本身不承载业务状态;Session 把真实数据放服务端、客户端只留一个 SessionID,JWT 则把用户信息自包含地签进令牌、服务端只验签不存储,所以三者不是替代而是互补,现代架构常组合使用。

Q2:JWT 为什么无法主动失效?有什么补救办法?

结论先行:因为 JWT 无状态,服务端不记录已签发的令牌,无法「撤销」一个还没过期的 Token。因为验证只靠签名,签出的 Token 在有效期内对任何持有者都有效;补救只能绕道——把有效期压到 15 分钟级别、用 Refresh Token 换新、把泄露的 Token/Refresh Token 加入黑名单强制失效。

Q3:分布式架构里为什么更倾向 JWT 而不是 Session?

结论先行:因为 JWT 自包含、无状态,各节点用同一密钥即可独立验签,无需访问共享存储。因为 Session 要求集群共享一份状态(Redis),引入网络依赖和单点;而 JWT 把身份信息放在令牌里,服务扩容、跨服务调用都不需要额外协调,天然贴合微服务的无状态假设。


Share this post on:

Previous Post
DDoS攻击详解:从僵尸网络到流量清洗
Next Post
页面置换算法——从OPT到LRU到Clock的演进