Cookie vs LocalStorage vs SessionStorage:浏览器三种存储对比
深入对比 Cookie、LocalStorage 和 SessionStorage 的容量、生命周期、HTTP 关系、隐私政策影响、SameSite 与 XSS 防护、HttpOnly 安全性、应用场景、GDPR 合规、IndexedDB 与 Web SQL 弃用、最佳实践。
现代 Web 应用需要在浏览器端存储数据,但不同的存储方式有不同的特性和适用场景。Cookie、LocalStorage 和 SessionStorage 是浏览器提供的三种主要存储机制,它们各有优缺点。选择正确的存储方式对应用的安全性、性能和用户体验至关重要。本文将深入对比这三种存储机制,帮助开发者做出明智的选择。
1. 三种存储机制概览
Cookie:HTTP 状态管理的古老方案
Cookie 是在 1994 年由 Netscape 浏览器引入的,至今仍是 HTTP 状态管理的标准方式。Cookie 是浏览器存储在本地的键值对,每个请求时自动发送给服务器。最初用于在无状态的 HTTP 上实现会话管理(Session),后来扩展为各种用途。
LocalStorage:永久客户端存储
LocalStorage 是 HTML5(2013)引入的 Web Storage API 的一部分。它允许网站在用户浏览器中永久存储数据,无需手动删除。数据按源(Origin)隔离,同一源的所有页面共享同一个 LocalStorage。
SessionStorage:临时会话存储
SessionStorage 也是 Web Storage API 的一部分,与 LocalStorage 非常相似,但仅在当前标签页/窗口打开期间有效。关闭标签页后自动清除。适用于需要在同一会话内传递数据但不需要长期保存的场景。
2. 容量对比:大小与限制
| 特性 | Cookie | LocalStorage | SessionStorage |
|---|---|---|---|
| 单个项大小 | 约 4KB | 5-10MB | 5-10MB |
| 单个域名总容量 | 约 180KB(多个 Cookie) | 5-10MB | 5-10MB |
| 跨域访问 | 可设置 Domain | 完全隔离 | 完全隔离 |
| 存储数据类型 | 字符串 | 字符串(需 JSON 序列化) | 字符串(需 JSON 序列化) |
为什么 Cookie 这么小?
Cookie 之所以限制在 4KB 左右,是因为每个 HTTP 请求都会自动发送所有 Cookie。如果 Cookie 太大,会增加网络开销。HTTP 头的总大小也有限制(通常 8KB),包含 Cookie 的数量和大小都会影响性能。
Storage 的 5-10MB 限制是浏览器特定的
localStorage 和 sessionStorage 的具体容量因浏览器而异:
- Chrome/Edge — 通常 10MB per origin
- Firefox — 10MB per origin
- Safari — 5MB per origin
- IE 11 — 10MB per origin
- 移动浏览器 — 通常 5MB 或更少
开发者应该查询 navigator.storage.estimate() 来检查实际可用空间。
3. 生命周期对比
Cookie:灵活的过期机制
Cookie 的生命周期由服务器在设置时指定,通过 Expires 或 Max-Age 属性控制:
Set-Cookie: sessionid=abc123; Max-Age=3600; Path=/
这个 Cookie 在 1 小时(3600 秒)后自动过期。没有 Expires/Max-Age 的 Cookie 称为会话 Cookie,浏览器关闭时自动删除。一旦 Cookie 过期,浏览器自动删除它。
LocalStorage:永久直到手动删除
LocalStorage 中的数据默认永不过期,除非:
- 用户手动清除浏览器数据
- JavaScript 代码调用
localStorage.removeItem(key)或localStorage.clear() - 浏览器清理存储(某些浏览器在磁盘空间不足时)
- 用户卸载浏览器或清除 App 数据(移动端)
SessionStorage:页面/标签页关闭自动清除
SessionStorage 的生命周期与标签页绑定。关键特性:
- 同一标签页内的所有页面共享 SessionStorage
- 新打开的标签页有独立的 SessionStorage(即使是同一网站)
- 关闭标签页立即清除数据
- 浏览器崩溃时数据可能丢失(取决于浏览器的恢复机制)
注意: LocalStorage 在隐私模式(Incognito)或无痕浏览中表现不同。大多数浏览器在隐私模式中仍允许 LocalStorage,但关闭窗口时清除数据。这可能导致同一网站在普通模式和隐私模式下行为不同。
4. HTTP 通信行为
Cookie:自动随请求发送
Cookie 的最大特性是自动性。浏览器会自动在每个 HTTP 请求中发送匹配的 Cookie:
GET /api/user HTTP/1.1 Host: example.com Cookie: sessionid=abc123xyz; userid=12345
这个自动发送的特性是 Cookie 用于服务器认证的原因。但这也意味着 Cookie 会增加每个请求的大小,包括静态资源请求。这是为什么现代网站通常为 CSS、JS、图片等静态资源使用独立的无 Cookie 域名(如 cdn.example.com)。
Storage:JavaScript 专属,不与服务器通信
LocalStorage 和 SessionStorage 完全是客户端存储,不与服务器通信。服务器无法直接读取 Storage 中的内容。JavaScript 必须显式读取 Storage 并在请求中发送:
// 手动读取和发送 const token = localStorage.getItem('authToken'); fetch('/api/user', { headers: { 'Authorization': 'Bearer ' + token } });
这种显式性提供了更多控制,但也要求开发者记得在每个请求中包含它。现代应用通常使用 fetch 拦截器(interceptor)或类似机制自动添加认证头。
跨域与 Cookie
Cookie 发送涉及跨域问题。默认情况下,跨域请求(CORS)不发送 Cookie。必须在客户端和服务器都显式启用:
// 客户端:启用 credentials fetch('https://api.other.com/data', { credentials: 'include' }); // 服务器:设置 CORS 头 Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: https://example.com
Storage 没有这种问题,因为它完全是域名隔离的,跨域根本无法访问。
6. XSS 与 CSRF 防护
XSS(跨站脚本)攻击
XSS 攻击注入恶意 JavaScript,在受害者浏览器中执行。如果敏感数据(如认证 Token)存储在 LocalStorage 或可访问的 Cookie 中,恶意脚本可以读取并发送到攻击者的服务器。
防护策略:HttpOnly Cookie
最好的防护 是使用 HttpOnly Cookie。即使网站遭受 XSS,恶意脚本也无法读取 HttpOnly Cookie,因此无法盗取 Token。HttpOnly Cookie 由浏览器自动在 HTTP 请求中发送,不需要 JavaScript。
建议: 所有认证 Token 都应该使用 HttpOnly Cookie,而不是 LocalStorage。如果必须用 Storage,使用内存变量(页面刷新后丢失),或定期轮换 Token。
CSRF(跨站请求伪造)攻击
CSRF 攻击利用浏览器的自动 Cookie 发送特性。攻击者让受害者访问恶意网站,该网站向受害者已登录的网站发送虚假请求(如转账),浏览器自动发送 Cookie,请求成功执行。
防护策略:SameSite 与 CSRF Token
两种主要防护方式:
- SameSite Cookie — 设置 SameSite=Lax 或 Strict,防止跨站请求自动发送 Cookie(现代浏览器支持)
- CSRF Token — 服务器在响应中生成随机 Token,JavaScript 必须在表单或请求头中包含它。Token 存储在 SessionStorage 或隐藏字段中(不是 Cookie)
现代应用通常同时使用两者:SameSite 作为浏览器级别的防护,CSRF Token 作为应用级别的防护。
Storage 与 XSS 的关系
LocalStorage 和 SessionStorage 无法防御 XSS。如果任何认证信息或敏感数据存储在 Storage 中,XSS 攻击脚本可以直接读取。这就是为什么存储在 Storage 中的数据应该是低敏感性的(用户偏好、缓存等),而不是认证 Token。
7. 隐私与 GDPR 合规
Cookie 与隐私政策
在欧盟和许多国家,使用 Cookie 存储个人数据需要用户明确同意。《通用数据保护规例》(GDPR)将 Cookie 分为:
- 必需 Cookie — 网站运行必需,无需额外同意(如会话 Cookie)
- 功能性 Cookie — 记录用户偏好,需要明确同意
- 分析 Cookie — 跟踪用户行为,需要明确同意
- 营销 Cookie — 用于广告投放,需要明确同意
LocalStorage 也受 GDPR 保护
这是许多开发者忽视的问题。虽然 Cookie 的合规要求广为人知,但 LocalStorage 和 SessionStorage 中的任何个人数据也受 GDPR 保护。存储用户 ID、邮箱、行为跟踪数据等都需要用户同意。
隐私保护的实践
合规建议:
- 实现同意管理系统(CMP),在用户同意前不加载 Cookie/追踪代码
- 明确在隐私政策中列出所有使用的 Cookie 和存储数据
- 为用户提供管理 Cookie 偏好的选项(Cookie Wall 违法)
- 定期审计 LocalStorage 和 SessionStorage 使用,检查是否存储敏感数据
- 在用户删除账户时,清除相关存储数据
三方 Cookie 的未来
Google Chrome 计划逐步弃用三方 Cookie(用于跨网站追踪的 Cookie)。这影响了广告和分析行业。开发者应该开始迁移到 First-Party Data 或新的隐私保护技术(如 Privacy Sandbox)。未来的 Web 会更加重视隐私。
8. 应用场景与最佳实践
何时使用 Cookie
用于服务器认证。 Cookie 的主要用途是实现会话管理。用户登录后,服务器发送会话 Cookie,浏览器在每个请求中自动发送。服务器根据 Cookie 识别用户身份。
- 认证 Token — 使用 HttpOnly、Secure、SameSite=Lax
- 用户偏好 — 可以使用 JavaScript 读取的常规 Cookie
- 追踪用户行为 — 需要用户同意(GDPR)
何时使用 LocalStorage
用于长期客户端存储。 LocalStorage 适合存储不需要发送给服务器的数据。
- 用户偏好设置 — 暗黑模式开关、语言选择
- 应用缓存 — 本地保存的草稿、离线数据
- 不应该存储 — 认证 Token、敏感个人信息
何时使用 SessionStorage
用于会话内的临时数据。 SessionStorage 适合只在当前标签页/窗口有效的数据。
- 多步表单 — 保存用户在不同步骤输入的数据
- 临时会话状态 — 当前页面的 UI 状态、搜索历史
- 跨域通信辅助 — postMessage 前的临时数据缓冲
现代最佳实践总结
认证 Token:HttpOnly Cookie 用户偏好:LocalStorage 临时数据:SessionStorage 服务器会话:带有 SameSite 的 Cookie 敏感个人数据:不存储在浏览器
9. IndexedDB 与 Web SQL 弃用
IndexedDB:下一代存储方案
IndexedDB 是一个更高级的客户端存储方案,支持更大的容量(通常 50MB+,取决于浏览器和用户设置)和更复杂的数据结构(对象存储、索引、事务)。与 Storage 的字符串存储不同,IndexedDB 可以存储任意 JavaScript 对象。
何时使用 IndexedDB
IndexedDB 适合需要大量数据和复杂查询的场景:
- 离线应用 — Service Worker + IndexedDB 实现完整离线功能
- 大量数据缓存 — 如完整的邮件列表或文档库
- 实时应用 — WebSocket 数据的本地缓存
- 媒体播放列表 — 离线视频/音频
Web SQL 已弃用
Web SQL 是早期尝试在浏览器中实现 SQL 数据库的 API。2010 年,W3C 官方声明 Web SQL 已弃用,不再进行标准化。主要原因:
- 浏览器实现差异大(底层使用 SQLite)
- SQL 注入风险
- IndexedDB 提供了更灵活的替代方案
虽然某些浏览器仍支持 Web SQL(出于兼容性),但不应该在新项目中使用。应该迁移到 IndexedDB。
Storage 与 IndexedDB 的选择
| 需求 | 使用 |
|---|---|
| 简单的键值对 | LocalStorage |
| 少量数据,快速访问 | SessionStorage |
| 大量数据,复杂查询 | IndexedDB |
| 服务器认证 | HttpOnly Cookie |
常见问题
Cookie、LocalStorage 和 SessionStorage 的最大区别是什么?
最大区别是生命周期和 HTTP 传输行为。Cookie 有设定的过期时间,每个请求自动发送给服务器;LocalStorage 永久存储直到手动删除;SessionStorage 在页面关闭时自动清除。Storage 不与服务器通信,仅用于客户端。
为什么要用 HttpOnly Cookie?
HttpOnly 标志阻止 JavaScript 访问 Cookie,防止 XSS 攻击脚本盗取敏感 Token。即使网站遭受 XSS,恶意脚本也无法读取 HttpOnly Cookie。对于登录认证 Token,应该总是设置 HttpOnly。
SameSite 属性有什么作用?
SameSite 防止跨站请求伪造(CSRF)攻击。设置为 Strict 时,Cookie 只在同站请求中发送;Lax 允许顶级导航;None 需要 Secure 标志。推荐使用 SameSite=Lax 平衡安全与用户体验。
LocalStorage 受 GDPR 监管吗?
是的。LocalStorage 中存储的任何个人数据都受 GDPR 保护,需要用户同意。虽然很多网站忽视了这一点,但法律上 LocalStorage 和 Cookie 同样需要合规。使用同意管理系统(CMP)并在隐私政策中明确说明。
可以在 LocalStorage 中存储认证 Token 吗?
不推荐。LocalStorage 中的数据可被 JavaScript 访问,XSS 攻击可以读取。最佳做法是使用 HttpOnly Cookie。如果必须用 LocalStorage,可以考虑使用内存变量(页面刷新后丢失)或定期轮换 Token。
多标签页共享 LocalStorage 吗?
是的。同一源的所有标签页、窗口、iframe 都共享 LocalStorage。如果一个标签页修改了 LocalStorage,其他标签页会看到更新(通过 storage 事件)。SessionStorage 不共享,每个标签页有独立的 SessionStorage。