Cookie:HTTP 的“记忆载体”
是什么?
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据。它本质上是一种存储机制和传输机制,而不是认证协议本身。由于 HTTP 是无状态协议,Cookie 的出现就是为了让浏览器在后续请求中自动携带这段数据,从而让服务器“记住”用户。
核心特点
- 自动携带:浏览器会根据域名规则,在每次请求时自动将 Cookie 放入 Request Header。
- 大小限制:通常限制在 4KB 左右。
- 安全性属性:可通过
HttpOnly(防 XSS 读取)、Secure(仅 HTTPS 传输)、SameSite(防 CSRF)等属性增强安全。 - 跨域限制:默认遵循同源策略,不支持跨域共享(除非特殊配置)。
工作原理
- 服务器通过
Set-Cookie响应头发送 Cookie 到浏览器。 - 浏览器按域/路径/过期时间存储 Cookie,并在后续请求中通过
Cookie请求头自动携带。 - 服务器解析请求中的 Cookie,根据内容执行个性化操作(如显示登录状态)。
一句话总结
Cookie 只是一个“信封”,里面装什么内容(Session ID 还是 Token),由开发者决定。
Session:服务端的“状态记录本”
是什么?
Session 是一种服务端状态管理机制。当用户登录后,服务器会在内存、数据库或 Redis 中创建一条会话记录,包含用户信息。然后服务器将该记录的 ID(Session ID)通过 Cookie 发送给客户端。
核心特点
- 状态存在服务端:用户数据存储在服务器,客户端仅持有 ID。
- 可控性:服务器可随时销毁 Session,强制用户下线。
- 分布式挑战:多服务器架构需共享 Session 存储(如 Redis)。
- 依赖传输载体:通常通过 Cookie 传递 Session ID,也可通过 URL 参数(不推荐)。
工作原理
- 用户提交登录凭证,服务器验证后创建 Session 并生成 Session ID。
- 服务器通过
Set-Cookie响应头发送 Session ID 到浏览器。 - 浏览器在后续请求中通过
Cookie请求头携带 Session ID。 - 服务器根据 Session ID 查找服务端存储的 Session 数据,验证用户身份。
一句话总结
Session 是“服务端记账,客户端只拿凭证”的经典模式。
Token:无状态的“通行证”
是什么?
Token 是一个自包含的访问凭证,通常是一串加密字符串。与 Session 不同,Token 模式下服务端不需要保存会话状态。验证 Token 的有效性完全依靠算法(签名/加密),而非查库。
核心特点
- 无状态:服务端无需存储 Token 信息,仅需验证其合法性。
- 轻量级:通常比 Session 更小,适合频繁传输。
- 灵活存储:可存在浏览器 Cookie、HTTP Header(推荐)、LocalStorage 或内存中。
- 有效期控制:通过设置过期时间限制 Token 生命周期。
工作原理
- 用户登录成功后,服务器生成 Token(如 JWT)并返回给客户端。
- 客户端存储 Token,并在后续请求中通过指定方式(如 Header)传递。
- 服务端接收请求后,直接验证 Token 的有效性(签名、过期时间等),无需查询数据库。
一句话总结
Token 把“查验身份”的计算压力从数据库查询转移到了 CPU 解密/验签上。
JWT (JSON Web Token):Token 的事实标准
是什么?
JWT 是 Token 的一种具体实现规范(RFC 7519)。它定义了 Token 的结构和签名方式,是目前最流行的 Token 格式。
核心特点
- 三段式结构:Header(算法声明)、Payload(用户信息)、Signature(签名)。
- 自描述性:Payload 包含用户身份和权限等声明(claims)。
- 无状态:服务端无需存储 Token,仅需验证签名。
- 跨域友好:适合前后端分离、移动端和微服务架构。
工作原理
- 服务器用密钥对 Header 和 Payload 进行签名,生成 Signature。
- 将三个部分用 Base64 编码后用
.连接,形成 JWT。 - 客户端存储 JWT,并在请求中通过
Authorization: Bearer <token>头部传递。 - 服务端接收 JWT 后,验证签名是否有效,解析 Payload 获取用户信息。
注意事项
- Payload 不加密:JWT 的 Payload 是 Base64 编码的明文,不要存储敏感数据。
- 无法主动撤销:一旦签发,除非设置极短有效期或引入黑名单机制,否则无法立即失效。
- 签名密钥保护:密钥泄露会导致 JWT 被伪造。
一句话总结
JWT 是一种标准化的、自描述的、可验证的 Token 格式。
OAuth2:授权的“委托协议”
是什么?
OAuth2 既不是存储机制,也不是凭证格式,而是一个授权框架(RFC 6749)。它解决的核心问题是:如何让用户在不暴露密码的前提下,授权第三方应用访问自己的资源?
核心特点
- 授权而非认证:OAuth2 负责授权第三方应用访问资源,不直接处理用户身份验证。
- 标准化流程:定义了明确的授权流程和角色分工。
- 多种授权模式:适应不同应用场景的需求。
- 令牌交换:通过授权码等中间凭证换取最终的访问令牌。
工作原理
以授权码模式为例:
- 用户访问客户端应用,触发跳转到授权服务器(如 Google、Facebook)。
- 用户在授权服务器登录并授权客户端访问其资源。
- 授权服务器返回授权码(Authorization Code)给客户端。
- 客户端用授权码向授权服务器换取 Access Token 和 Refresh Token。
- 客户端使用 Access Token 访问资源服务器(如用户邮箱、照片)。
注意事项
- 需配合认证协议:如 OpenID Connect (OIDC) 才能实现完整认证。
- 密钥轮换:定期更新签名密钥以增强安全性。
- 令牌安全:Access Token 应通过 HTTPS 传输,避免泄露。
一句话总结
OAuth2 是“我不给你密码,但我允许你代表我做事”的安全授权标准。
技术全景对比表
下表总结了五大技术的核心区别:
| 维度 | Cookie | Session | Token | JWT | OAuth2 |
|---|---|---|---|---|---|
| 本质 | 存储/传输机制 | 服务端状态管理 | 访问凭证 | Token 的标准格式 | 授权框架 |
| 状态 | 客户端存储 | 服务端有状态 | 服务端无状态 | 服务端无状态 | 协议层面无状态 |
| 存储位置 | 浏览器 | 服务器内存/Redis | 客户端(LocalStorage/Cookie) | 同 Token | 不涉及存储 |
| 大小限制 | 约4KB | 无限制 | 无限制 | 无限制 | 无限制 |
| 跨域支持 | ❌ 受限 | ❌ 受限 | ✅ 友好 | ✅ 友好 | ✅ 专为跨域设计 |
| 移动端适配 | ❌ 差(依赖浏览器) | ❌ 差 | ✅ 好 | ✅ 好 | ✅ 好 |
| 可扩展性 | - | ❌ 需共享存储 | ✅ 天然支持 | ✅ 天然支持 | ✅ 天然支持 |
| 能否主动失效 | ✅ 删除即可 | ✅ 删除服务端记录 | ❌ 需额外机制(如黑名单) | ❌ 需额外机制(如黑名单) | ✅ Refresh Token 轮换 |
| 典型用途 | 传递 Session ID 或 JWT | 传统 Web 登录 | API 认证 | 现代 API 认证 | 第三方授权/SSO |
| 安全性 | 依赖属性(HttpOnly, Secure) | 依赖服务端安全 | 依赖签名算法 | 依赖签名算法 | 依赖流程实现 |
数据来源:
场景化技术选型指南
传统服务端渲染 Web 应用
推荐方案:Cookie + Session
- 原因:成熟稳定,服务端可控,适合内部系统或不需要对外暴露 API 的场景。
- 最佳实践:
- 使用
HttpOnly和Secure属性保护 Cookie。 - 设置合理的 Session 过期时间。
- 在分布式环境中使用 Redis 等共享存储。
- 使用
前后端分离应用
推荐方案:JWT + HTTP Header
- 原因:无状态、易扩展、跨域友好,适合 API 驱动的现代应用。
- 最佳实践:
- 将 JWT 存储在
HttpOnly + Secure + SameSite=Strict的 Cookie 中,或通过 Header 传递。 - 设置短期有效期(如15分钟),配合 Refresh Token 实现自动刷新。
- 避免在 URL 或 LocalStorage 中存储 JWT。
- 将 JWT 存储在
移动端应用
推荐方案:JWT + 安全存储
- 原因:轻量级、适合移动网络,且能实现离线访问。
- 最佳实践:
- 使用 Android Keystore 或 iOS Keychain 加密存储 Token。
- 通过 HTTPS 传输 Token,避免中间人攻击。
- 定期刷新 Token,减少泄露风险。
微服务架构
推荐方案:JWT + OAuth2
- 原因:无状态设计适合分布式系统,JWT 支持细粒度权限控制。
- 最佳实践:
- 使用 OAuth2 的 ClientCredentials 模式实现服务间通信。
- 在 JWT 中包含微服务所需的权限声明(如
read:users,write:products)。 - 避免完全依赖网关验证,各微服务应实施细粒度授权控制。
第三方登录
推荐方案:OAuth2 + JWT
- 原因:OAuth2 提供安全授权流程,JWT 作为 Access Token 实现无状态验证。
- 最佳实践:
- 使用 OAuth2 的 Authorization Code 模式(推荐)或 PKCE(移动端)。
- 授权服务器可返回 JWT 作为 Access Token,资源服务器验证签名即可。
- 配合 OpenID Connect (OIDC) 实现完整用户认证。
企业内网 SSO
推荐方案:SSO + JWT
- 原因:SSO 提供单点登录体验,JWT 实现跨系统无状态验证。
- 最佳实践:
- 统一认证中心(如 Keycloak)生成 JWT 并通过 Cookie 或 Header 传递。
- 各子系统验证 JWT 签名,无需重复登录。
- 可结合 OAuth2 实现跨公司授权。
常见误区澄清
误区 1:“JWT 比 Session 更安全”
- 真相:JWT 和 Session 的安全性取决于实现方式。Session 可随时在服务端销毁,而 JWT 一旦签发,在过期前无法主动撤销。因此,在敏感场景中,Session 可能更安全,但 JWT 更适合分布式系统。
误区 2:“用了 OAuth2 就不需要 JWT 了”
- 真相:OAuth2 是授权框架,它规范了授权流程,但未限定令牌格式。JWT 是一种流行的令牌格式,常被 OAuth2 使用作为 Access Token。两者是互补关系,而非替代关系。
误区 3:“Token 应该存在 LocalStorage 里”
- 真相:LocalStorage 易受 XSS 攻击,Token 应优先存在
HttpOnly + Secure + SameSite=Strict的 Cookie 中,或通过 HTTP Header 传递。若必须使用 LocalStorage,应结合加密和短期有效期。
误区 4:“Cookie 就是 Session”
- 真相:Cookie 是传输机制,Session 是服务端状态管理。Cookie 可以存储任何数据(如 JWT),而 Session 需要服务端维护状态。两者是不同层次的概念,可以独立使用或结合使用。
误区 5:“OAuth2 可以替代 JWT”
- 真相:OAuth2 处理授权流程,JWT 是具体令牌格式。OAuth2 可以返回 JWT 作为 Access Token,两者结合使用更为常见。JWT 也可独立用于 API 认证。
技术关系图
这五者并非互斥关系,而是不同层次、不同职责的技术组件:
- Cookie 负责"搬运"
- Session 负责"记账"
- Token 负责"证明"
- JWT 负责"标准化证明"
- OAuth2 负责"制定授权规则"
它们可以组合使用,例如:
- 用户通过 OAuth2 授权第三方应用。
- 授权服务器返回 JWT 作为 Access Token。
- 客户端将 JWT 存储在 Cookie 中,并在请求中自动携带。
- 资源服务器验证 JWT 签名,无需服务端状态存储。
总结
理解这五个概念的区别,关键在于把握它们的本质定位和技术层次:
- Cookie:HTTP 协议的无状态管理机制,负责数据存储和传输。
- Session:服务端状态管理机制,依赖 Cookie 传递 ID。
- Token:通用访问凭证,服务端无状态验证。
- JWT:Token 的标准化实现,结构清晰且可验证。
- OAuth2:授权框架,定义了令牌交换和资源访问的流程。
没有最好的技术,只有最适合场景的技术。选择时应考虑:
- 安全性需求(如是否需要主动失效)
- 扩展性需求(如是否需要支持分布式系统)
- 跨域/移动端适配
- 实现复杂度与维护成本