Cookie、Session、Token 与 JWT 的关系
从状态、凭证角色、凭证格式和传输机制四个维度区分 Cookie、Session、Token、JWT,避免把它们误当成互斥认证方案。
[!info] related notes
- 所属 MOC: Node.js 后端面试 MOC, 后端开发 MOC, HTTP 与前端网络请求 MOC, 安全 MOC
- 原子概念: Server-side Session 鉴权, Access Token, Refresh Token, JWT
- 关系笔记: Stateful、Stateless 与 Hybrid 认证架构, HTTP 的状态保存方案
- 浏览器安全: HttpOnly Cookie, SameSite, CSRF 跨站请求伪造, Cookie 和 LocalStorage 的区别
Cookie、Session、Token 与 JWT 的关系
范围
Cookie、Session、Token、JWT 经常被放在一起比较,但它们并不是四种互斥的“认证方案”。更准确的理解是把认证系统拆成四个维度。
四层心智模型
State
→ 长期登录状态保存在哪里?
→ Server-side Session / Grant
Credential role
→ 客户端拿什么凭证做什么?
→ Session Token / Access Token / Refresh Token
Credential format
→ 凭证长什么样?
→ JWT / opaque random string
Transport / storage
→ 浏览器怎么保存和发送?
→ Cookie / Authorization Header / memory 等
因此一个真实系统完全可以同时使用 Cookie、Session、Token 和 JWT。
Cookie:浏览器的存储与自动携带机制
Cookie 是浏览器和 HTTP 之间的状态机制。服务器通过 Set-Cookie 写入,浏览器之后根据 Domain、Path、Secure、SameSite 等规则自动携带。
Cookie
≠ Session
≠ JWT
Cookie 只是“值怎么被浏览器保存和发送”。这个值可以是:
- 随机 Session ID;
- Refresh Token;
- 签名 Session Cache;
- 甚至 Access Token。
常见安全属性:
HttpOnly
→ JavaScript 不能直接读取 Cookie 值
Secure
→ 只经 HTTPS 发送
SameSite
→ 限制跨站场景下自动携带
HttpOnly 降低 XSS 直接窃取凭证的风险,但不等于自动解决 CSRF,因为浏览器仍可能自动发送 Cookie。
Session:服务端登录生命周期状态
Session 的核心不是 Cookie,而是:
服务端保存“这次登录现在是否仍然有效”的权威状态。
例如:
Session
├─ id
├─ user_id
├─ expires_at
├─ revoked_at
├─ device
└─ metadata
客户端通常只持有能够定位或访问这份状态的凭证。
纯 Session 方案可以是:
HttpOnly Cookie
→ opaque session token
→ Session Store
完全不需要 JWT。
Token:泛指客户端持有的凭证
Token 不是某种固定格式,也不天然意味着无状态。
常见角色:
Session Token
→ 定位服务端 Session
Access Token
→ 高频调用受保护 API
Refresh Token
→ 换取新的 Access Token
这些 Token 都可以是 opaque random string;其中 Access Token 也常使用 JWT。
JWT:一种结构化签名格式
JWT(JSON Web Token)是 Token 的一种表示格式,而不是一整套登录生命周期方案。
Header.Payload.Signature
签名主要证明:
- Payload 在签发后没有被篡改;
- Token 由持有对应签名密钥的一方签发。
它不天然证明:
- 当前 Session 仍然 live;
- 用户没有被封禁;
- Role/权限没有变化;
- 当前用户拥有某个具体资源。
所以:
JWT
= credential format
Access / Refresh
= credential role
Session
= server-side state model
Cookie
= browser transport/storage mechanism
三种常见组合
1. Opaque Session
Browser Cookie
→ random session token
→ Session Store
每个请求查实时 Session 状态,撤销简单、语义清晰。
2. Pure Stateless Access Token
Client
→ self-contained signed Access Token
→ Resource Server local verify
普通请求不查 Session Store,但已签发 Token 在 exp 前较难立即撤销。
3. Hybrid
长期 Session / Grant
↓ issue
短期 Access Token
↓
普通 API 本地验证
Access Token 过期
↓
Refresh Token
↓
回 Auth Server 检查 Session / Grant
↓
签发新 Access Token
它把高频请求的无状态快路径,与长期登录生命周期的有状态控制结合起来。
Browser 场景的常见组合
一种常见设计是:
短期 Access Token
→ memory
→ Authorization: Bearer
长期 Refresh Token
→ HttpOnly + Secure Cookie
→ 浏览器自动携带到 refresh endpoint
Server-side Session / Grant
→ Redis / DB / Auth Store
→ 控制 revoke / expiry / device lifecycle
但普通 Browser Web App 也完全可以直接使用 opaque Session Cookie,不必为了“现代”而额外引入 JWT 和 Refresh Token。
Authentication 与 Authorization 仍要分开
凭证验证成功
→ 建立 principal
Role / scope
→ 粗粒度能力
Ownership / resource state
→ 当前具体资源是否允许操作
即使 Access Token 中有 user_id、role、scope,也不能自动证明用户有权修改任意 Assessment 或 Order。
常见误区
- “Cookie vs Token 二选一” → Token 可以放在 Cookie。
- “Session 就是一种 Cookie” → Session 是服务端状态,Cookie 常用来携带 Session Token。
- “JWT 就是认证方案” → JWT 只是凭证格式。
- “Token 一定无状态” → opaque token 和 JWT 都可以绑定服务端状态。
- “Refresh Token 一定是 JWT” → 完全不需要。
- “JWT 验证成功就完成授权” → 仍可能需要当前 Session、User 和资源级 Policy。
- “Session 是旧技术,JWT 是现代替代品” → 不成立;选择取决于状态、撤销、规模和客户端类型。
最短记忆
Session 管登录生命周期,Token 是客户端凭证,JWT 是 Token 格式,Cookie 管浏览器如何保存和发送。真正的架构问题是:状态放哪、凭证做什么、凭证长什么样、什么时候回服务端查实时状态。
学习检查
不看正文回答:
- Cookie、Session、Token、JWT 为什么不是四种互斥认证方案?
- “状态放在哪里”“凭证做什么”“凭证长什么样”“浏览器怎么携带”分别属于哪一层?
- 为什么 Access Token 可以是 JWT,也可以不是 JWT?
- 为什么 Token 放进 Cookie 后,仍然要分别讨论 Token 角色与 Cookie 安全属性?
- Pure Stateless 与 Hybrid 认证架构在撤销和高频验证上有什么取舍?
- JWT 验证通过后,为什么仍不能自动推出资源级 Authorization 成功?
- 给一个 Browser Web App,设计一套 session/token/cookie 组合并解释每层职责。