| 特性 | Cookie | localStorage | sessionStorage |
|---|---|---|---|
| 存储容量 | 极小 (4KB) | 大 (~5MB) | 大 (~5MB) |
| 生命周期 | 默认会话级 (Session cookie),设置过期时间后可持久化 | 永久有效,除非手动清除 | 窗口关闭即销毁 (Tab级) |
| 服务端通信 | 每次 HTTP 请求都会自动携带 | 不参与通信,仅在前端使用 | 不参与通信,仅在前端使用 |
| 访问权限 | 同源 | 同源 | 同源 |
| 安全性 | 可设置 HttpOnly 防止 JS 访问 | 无法设置,易被 XSS 攻击 | 无法设置,易被 XSS 攻击 |
最古老的机制,设计初衷是让无状态的 HTTP 能够标识用户状态(Session ID)。因为每次请求都会带上,所以如果存储无用数据,会浪费带宽。
关键属性:
HttpOnly: 禁止 document.cookie 访问,防止 XSS 攻击窃取 Token。Secure: 仅在 HTTPS 传输。SameSite: 防止 CSRF 攻击 (Strict, Lax, None)。
Strict: 完全禁止第三方 Cookie 发送。Lax (默认): GET 导航等安全操作允许发送。适合存储较大且不需要随请求发送的数据。例如:
生命周期仅限于当前标签页 (Tab)。如果用户打开两个该网站的标签页,它们的 sessionStorage 是隔离的。适合存储临时表单数据、单次访问的状态。
(面试题:sessionStorage 在新开标签页可以共享吗?- 只有通过 window.open 或 target="_blank" 打开的同源标签才有可能复制旧 Session,通常是独立的。)
当存储空间需求极大 (> 50MB) 或需要更复杂的事务支持/索引查询时,应使用 IndexedDB。它是浏览器内置的非关系型数据库,支持二进制存储。
不要将 Token 存放在 localStorage 中,一旦脚本注入就能轻易窃取。
最佳实践:Token 存放在 HttpOnly Cookie 中,这样脚本无法读取,但 API 请求会自动带上。配合 CSRF Token 防御 CSRF。
原生没有。需要手动封装:存储时写入 { value, expire: Date.now() + 1000 },读取时判断是否过期,过期则删除。