cookie、session、token、JWT(JSON Web Token)均是Web开发中用于身份认证、会话管理的技术,但它们的实现方式、运行机制和适用场景有显著差异。以下从概念、运行流程、特点及区别四个维度详细说明:
一、基本概念
1. Cookie
Cookie是客户端(浏览器)存储的小型文本数据 ,由服务器通过HTTP响应头(Set-Cookie)下发,客户端(浏览器)会自动将其存储,并在后续向该服务器的请求中通过HTTP请求头(Cookie)携带,用于标识用户身份或传递状态。
- 大小限制:通常4KB以内,只能存储文本。
- 生命周期:可设置过期时间(
Expires或Max-Age),过期后自动删除;若不设置,为"会话Cookie",关闭浏览器后消失。
2. Session(会话)
Session是服务器端存储的会话数据 ,用于记录客户端(用户)的状态。服务器为每个客户端生成唯一的sessionID(通常通过Cookie传递给客户端),客户端后续请求携带sessionID,服务器通过sessionID找到对应的Session数据(存储在服务器内存、数据库或缓存中)。
- 核心:服务器通过
sessionID关联客户端状态,数据存储在服务器,客户端仅保存sessionID。
3. Token(令牌)
Token是服务器生成的一串字符串 ,作为客户端请求的"凭证"。客户端登录后,服务器验证用户信息并生成Token,返回给客户端;客户端存储Token(如Cookie、localStorage),后续请求通过请求头(如Authorization: Bearer <token>)携带Token,服务器验证Token有效性(无需存储Token本身,或仅存储黑名单)。
- 核心:无状态(服务器无需存储完整会话数据),Token自身包含验证所需信息(或通过算法验证)。
4. JWT(JSON Web Token)
JWT是一种具体的Token实现标准,定义了紧凑且自包含的JSON对象,用于在各方之间安全传递信息。信息通过数字签名验证,可确保完整性和真实性。
- 结构:由三部分组成(用
.分隔),分别是头部(Header) 、载荷(Payload) 、签名(Signature) ,整体为字符串(如eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkiLCJuYW1lIjoiSm9obiBEb2UifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c)。
二、运行流程
1. Cookie的流程
- 客户端首次请求服务器(如登录)。
- 服务器处理请求后,通过
Set-Cookie响应头向客户端下发Cookie(如Set-Cookie: user_id=123; Max-Age=3600)。 - 客户端(浏览器)存储Cookie,并在后续请求中自动通过
Cookie头携带(如Cookie: user_id=123)。 - 服务器通过Cookie中的数据识别用户。
2. Session的流程
- 客户端首次请求服务器(如登录)。
- 服务器验证用户信息后,创建Session(存储用户状态,如
{user_id:123, username:"张三"}),生成唯一sessionID(如sid=abc123)。 - 服务器通过
Set-Cookie将sessionID下发给客户端(如Set-Cookie: sid=abc123; HttpOnly)。 - 客户端后续请求通过
Cookie头携带sessionID。 - 服务器通过
sessionID查询对应的Session数据,验证用户身份并处理请求。
3. Token的通用流程
- 客户端提交登录信息(如账号密码)。
- 服务器验证通过后,生成Token(如随机字符串+用户ID加密),返回给客户端。
- 客户端存储Token(如
localStorage.setItem('token', 'xxx'))。 - 后续请求中,客户端通过请求头(如
Authorization: Token xxx)携带Token。 - 服务器验证Token(如解密Token获取用户ID,或查询黑名单确认未失效),通过则处理请求。
4. JWT的流程
- 客户端提交登录信息。
- 服务器验证通过后,生成JWT:
- 头部(Header):声明算法(如
HS256)和类型(JWT),Base64编码。 - 载荷(Payload):存储非敏感数据(如用户ID、过期时间
exp),Base64编码。 - 签名(Signature):用服务器密钥(
secret)对"头部+载荷"签名(如HS256(Header + "." + Payload, secret))。 - 三部分拼接为JWT,返回给客户端。
- 头部(Header):声明算法(如
- 客户端存储JWT(如localStorage),后续请求通过
Authorization: Bearer <jwt>携带。 - 服务器验证JWT:
- 拆分JWT为头部、载荷、签名。
- 用相同密钥和算法重新计算签名,与JWT中的签名比对(一致则未被篡改)。
- 检查载荷中的过期时间(
exp),确认未过期。 - 验证通过后,从载荷中获取用户信息(如用户ID),处理请求。
三、核心特点
| 技术 | 存储位置 | 服务器状态 | 安全性(默认) | 性能 | 扩展性 | 典型场景 |
|---|---|---|---|---|---|---|
| Cookie | 客户端(浏览器) | 无(数据在客户端) | 较低(易被篡改、窃取) | 高(仅传递文本) | 差(大小限制) | 记住登录状态、购物车 |
| Session | 服务器(内存/数据库) | 有状态(需存储session数据) | 较高(数据在服务器) | 中(需查询session) | 差(服务器存储压力) | 单体应用的会话管理 |
| Token | 客户端(Cookie/localStorage) | 无状态(服务器可无需存储) | 中(依赖签名/加密) | 高(验证逻辑简单) | 好(分布式友好) | 移动端API、第三方登录 |
| JWT | 客户端(同上) | 无状态(自包含信息) | 中(签名防篡改,载荷可解码) | 高(无需查询数据库) | 极好(跨服务/跨域) | 分布式系统、微服务认证 |
四、关键区别
-
存储位置与服务器依赖
- Cookie:存储在客户端,服务器无需存储数据,仅通过客户端携带的Cookie识别状态。
- Session:数据存储在服务器,客户端仅存
sessionID,服务器依赖sessionID查询数据(有状态)。 - Token/JWT:数据(或核心信息)存储在客户端,服务器通过算法验证有效性(无状态,服务器无需存储完整会话数据)。
-
安全性
- Cookie:易受XSS(跨站脚本)和CSRF(跨站请求伪造)攻击,需通过
HttpOnly(防XSS读取)、Secure(仅HTTPS传输)、SameSite(防CSRF)等属性增强安全。 - Session:数据在服务器,相对安全,但
sessionID通过Cookie传递,仍可能面临CSRF风险;若服务器被入侵,会话数据可能泄露。 - Token/JWT:若存储在localStorage,易受XSS攻击;若存储在Cookie,需同样配置安全属性。JWT的载荷可Base64解码(非加密),不可存储敏感信息(如密码),但签名可确保未被篡改。
- Cookie:易受XSS(跨站脚本)和CSRF(跨站请求伪造)攻击,需通过
-
扩展性
- Session:服务器需存储会话数据,在分布式系统中需共享Session(如用Redis集中存储),否则多服务器间会话不互通,扩展性差。
- Token/JWT:服务器无需存储数据,天然支持分布式(多服务器用同一密钥验证),扩展性极好,适合微服务、跨域场景。
-
撤销机制
- Session:服务器可直接删除Session数据,即时撤销会话(如强制用户登出)。
- Token/JWT:若未设计黑名单,一旦生成无法即时撤销(需等过期);若需即时撤销,需服务器存储"失效Token黑名单",会增加服务器存储成本(部分失去无状态优势)。
-
数据包含
- Cookie:仅能存储少量文本,且需客户端携带。
- Session:服务器可存储大量数据(如用户权限、购物车详情)。
- JWT:载荷可包含非敏感数据(如用户ID、角色),减少服务器查询数据库的次数(自包含特性)。
总结
- Cookie:适合存储少量非敏感数据(如登录状态标记),依赖浏览器自动携带。
- Session:适合单体应用的会话管理,服务器可控性强,但扩展性差。
- Token:适合无状态场景(如移动端API),灵活性高,需自行设计验证逻辑。
- JWT:是Token的标准化实现,适合分布式、跨服务认证,自包含信息减少查询,但需注意安全存储和撤销机制。
实际开发中,常结合使用(如SessionID存储在Cookie中,JWT通过Authorization头传递),需根据安全性、扩展性需求选择。