由于 HTTP 是无状态协议(每次请求独立),服务器无法"记住"用户身份。Cookie 和 Session 正是为了解决"会话跟踪"问题而诞生的两大核心技术。 简单来说:Cookie 是客户端的"身份证",Session 是服务端的"档案室"。
一、 什么是 Cookie?(客户端的"通行证")
Cookie 是服务器生成、存储在用户浏览器(客户端)中的小型文本文件(通常 < 4KB),由键值对组成。 浏览器每次发起 HTTP 请求时,会自动将符合规则的 Cookie 携带在请求头(Cookie 字段)中发送给服务器。
1.核心特征:
- 存储位置:客户端(浏览器)。
- 生命周期 :分为会话级 Cookie (浏览器关闭即失效)和持久化 Cookie (设置了
Expires或Max-Age,存储在硬盘上)。
2.关键属性(安全相关):
HttpOnly:禁止 JavaScript 读取,有效防御 XSS(跨站脚本攻击) 。Secure:仅允许通过 HTTPS 加密传输,防止中间人窃听。SameSite:限制跨站请求携带,用于防御 CSRF(跨站请求伪造) 。
3.Cookie 的典型应用场景:
记住用户登录状态(存 SessionID)、记录浏览偏好(主题色、语言)、电商购物车(非登录态)等。
二、什么是 Session?(服务端的"档案室")
Session 是服务器端为解决身份认证而开辟的内存/缓存空间 。当用户首次访问时,服务器创建一个唯一的 Session 对象(对应一个 SessionID),并利用 Cookie 将 SessionID 返回给客户端存储。
1.核心特征:
- 存储位置:服务器端(内存、Redis、数据库)。
- 数据容量:无大小限制(受服务器内存/存储限制),适合存储复杂的用户信息(如用户对象)。
- 生命周期 :通常设置超时时间(如 30 分钟无操作则失效),主动调用
invalidate()可立即销毁。
2.工作机制流程:
用户登录成功 → 服务器创建 Session 并存入用户信息 → 服务器生成 SessionID 并通过 Set-Cookie 发给浏览器 → 浏览器后续请求自动携带该 Cookie → 服务器根据 SessionID 取出对应 Session 数据,即完成身份识别。
三、核心区别对比(面试高频)
| 维度 | Cookie | Session |
|---|---|---|
| 存储位置 | 浏览器客户端 | 服务器端(内存/Redis) |
| 存储容量 | 小(单个约 4KB) | 大(几乎无限制) |
| 安全性 | 低(明文存储,易被篡改和窃取) | 高(数据在服务端,客户端只存 ID) |
| 性能消耗 | 低(不占用服务器资源) | 高(并发用户多时占用大量内存) |
| 分布式支持 | 天然支持(客户端自动携带) | 困难(需解决多台服务器 Session 共享问题) |
| 跨域/跨设备 | 支持(浏览器自动管理) | 依赖 Cookie 传递 ID,需额外处理 |
四、为什么 Session 依赖 Cookie?(例外情况)
绝大多数 Web 框架(如 Java HttpSession、PHP SESSION)默认使用 Cookie 来传输 SessionID。
如果客户端禁用 Cookie 怎么办?
采用 URL 重写 ,将 SessionID 作为 URL 参数附加在地址后面(如 url?jsessionid=xxx),但这种方式极不安全且影响 SEO,现代应用中很少使用。
五、分布式场景下的痛点与解决方案(进阶)
单机 Session 无法在集群中共享。假设用户第一次请求落在服务器 A(存储了 Session),第二次请求被负载均衡到服务器 B(没有该 Session),用户就会被踢下线。
主流解决方案:
- Session 粘滞(Sticky Session) :负载均衡器将同一用户的请求始终转发到同一台服务器(不推荐,容灾差)。
- Session 集中式存储(推荐) :将 Session 统一存放到Redis 或Memcached中。所有服务器去同一个缓存中读写,实现 Session 共享(例如 Spring Session + Redis 方案)。
六、现代技术演进:Session 的挑战与 JWT 的兴起
在前后端分离和微服务架构下,传统 Session 面临跨域、移动端不支持 Cookie 自动管理、CSRF 攻击等问题。因此,无状态的 JWT(JSON Web Token) 越来越流行。
- Session :有状态。服务器必须存储 Session 数据,查询 I/O 耗时,且注销时必须清除服务端数据。
- JWT :无状态。用户信息加密在 Token 字符串中,服务器只需验证签名,无需存储,天然支持分布式,且支持跨域和移动端。
注意 :JWT 虽然解决了存储问题,但其存在无法主动失效 (签发后有效期内无法销毁)和体积较大 (每次请求携带)的缺点。在需要实时踢人、修改权限立即生效的场景下,Redis + Session 依然是更可控的选择。