前端基础
从 Cookie 到 localStorage 理解浏览器本地存储
这篇笔记记录一下我对浏览器里几种常见本地存储方式的理解。 一开始我经常把这些名字混在一起: 它们看起来都能在浏览器里保存一点数据,但生命周期、是否会自动发送给服务器、适合放什么东西,其实差别很大。 后来我发现,可以先抓住一个问题: 再继续看它需要保存多久、是否只属于当前标签页、是否涉及安全信息。 先说结论 可以先记住几

这篇笔记记录一下我对浏览器里几种常见本地存储方式的理解。
一开始我经常把这些名字混在一起:
Cookie
sessionStorage
localStorage它们看起来都能在浏览器里保存一点数据,但生命周期、是否会自动发送给服务器、适合放什么东西,其实差别很大。
后来我发现,可以先抓住一个问题:
这份数据是给服务器看的,还是只给前端自己用的?再继续看它需要保存多久、是否只属于当前标签页、是否涉及安全信息。
先说结论
可以先记住几句话:
- Cookie 会随着符合条件的 HTTP 请求自动发送给服务器。
- localStorage 主要给前端长期保存少量数据,除非手动删除,否则一般会一直存在。
- sessionStorage 只在当前标签页会话中存在,关闭标签页后通常就没了。
- Cookie 适合保存服务器需要识别的状态,比如登录凭证,但要认真设置安全属性。
- localStorage 和 sessionStorage 适合保存前端状态,不适合保存高敏感凭证。
- 三者容量都不适合放大量数据,复杂离线数据更适合考虑 IndexedDB。
如果用一句话粗略区分:
Cookie 偏服务端通信,localStorage 和 sessionStorage 偏前端本地状态。Cookie 是什么
Cookie 是浏览器保存的一小段键值数据。
服务端可以通过响应头告诉浏览器保存 Cookie:
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Lax之后浏览器访问同一个站点里符合条件的接口时,会自动带上:
Cookie: session_id=abc123这就是 Cookie 和另外两种存储最大的区别。
localStorage 和 sessionStorage 只是放在浏览器里,默认不会跟着请求走。Cookie 则天然参与 HTTP 请求。
Cookie 的生命周期
Cookie 的生命周期主要看有没有设置过期时间。
如果没有设置 Expires 或 Max-Age,它通常是会话 Cookie。浏览器会话结束后可能被清理。
Set-Cookie: session_id=abc123如果设置了 Max-Age:
Set-Cookie: token=abc123; Max-Age=86400表示 Cookie 最多保存 86400 秒。
如果设置了 Expires:
Set-Cookie: token=abc123; Expires=Wed, 10 Jun 2026 10:00:00 GMT表示到指定时间后过期。
实际项目里,我更喜欢把登录态 Cookie 的过期时间和后端会话或令牌有效期一起设计,不要让前端以为自己还登录着,后端却已经不认了。
Cookie 常见应用场景
Cookie 常见用在这些地方:
- 保存 Session ID。
- 保存刷新令牌或登录凭证。
- 记录灰度发布、A/B 测试分组。
- 保存语言、地区等服务端也需要读取的偏好。
- 做一些简单的跨页面状态识别。
如果后端需要在每次请求时识别用户,Cookie 很自然。
例如传统 Session 登录里,浏览器保存的是:
session_id=abc123服务器根据这个 ID 去自己的存储里查当前用户是谁。
Cookie 的几个重要属性
Cookie 好用,但也容易出安全问题。
HttpOnly
Set-Cookie: session_id=abc123; HttpOnly设置以后,前端 JavaScript 不能通过 document.cookie 读取它。
这对登录凭证很重要。即使页面里出现 XSS 漏洞,攻击者也更难直接偷走 Cookie 内容。
Secure
Set-Cookie: session_id=abc123; Secure表示只在 HTTPS 请求中发送。
正式环境里的登录 Cookie 通常都应该设置。
SameSite
Set-Cookie: session_id=abc123; SameSite=Lax它主要用来减少 CSRF 风险。
常见值有:
| 值 | 大概含义 |
|---|---|
Strict | 跨站场景基本不发送 |
Lax | 常见跳转场景可以发送,跨站表单等场景受限 |
None | 跨站也发送,但通常必须配合 Secure |
如果是普通后台系统,Lax 经常是比较稳的默认选择。
localStorage 是什么
localStorage 是浏览器提供给前端的一种持久化键值存储。
写入:
localStorage.setItem("theme", "dark");读取:
const theme = localStorage.getItem("theme");删除:
localStorage.removeItem("theme");它只能保存字符串。如果要保存对象,需要自己序列化:
localStorage.setItem("userSettings", JSON.stringify(settings));读取时再解析:
const settings = JSON.parse(
localStorage.getItem("userSettings") ?? "{}",
);localStorage 的生命周期
localStorage 没有默认过期时间。
只要用户不主动清理浏览器数据,或者代码不手动删除,它通常会一直存在。
这很适合保存一些长期偏好:
- 主题模式。
- 语言偏好。
- 侧边栏是否折叠。
- 表格列配置。
- 最近使用的筛选条件。
- 本地草稿。
但也正因为它保存得久,不适合随便放敏感信息。
sessionStorage 是什么
sessionStorage 的 API 和 localStorage 很像:
sessionStorage.setItem("step", "2");
const step = sessionStorage.getItem("step");区别在生命周期和作用范围。
sessionStorage 通常只属于当前标签页。
同一个网站打开两个标签页,它们的 sessionStorage 一般不是同一份。关闭标签页后,这份数据也会被清掉。
sessionStorage 的应用场景
sessionStorage 适合保存只和当前页面流程有关的数据:
- 多步骤表单的临时步骤。
- 当前标签页里的临时搜索条件。
- 支付或授权跳转前后的短暂状态。
- 防止刷新后丢失的页面临时数据。
例如一个三步表单,用户刷新页面时不想从第一步重新开始,可以把当前步骤暂时保存到 sessionStorage。
sessionStorage.setItem("createOrderStep", String(currentStep));但是关闭标签页以后,这个状态就不需要继续保留了。
三者对比
可以用一张表记住:
| 对比项 | Cookie | localStorage | sessionStorage |
|---|---|---|---|
| 是否自动随请求发送 | 会 | 不会 | 不会 |
| 主要使用方 | 前端和服务端 | 前端 | 前端 |
| 生命周期 | 可配置,或浏览器会话 | 通常长期保存 | 当前标签页会话 |
| 容量 | 较小 | 比 Cookie 大 | 比 Cookie 大 |
| 适合保存 | 登录标识、服务端需要的状态 | 长期前端偏好 | 临时页面状态 |
| JS 能否读取 | 取决于 HttpOnly | 可以 | 可以 |
登录信息到底放哪里
这个问题很常见。
如果使用 Cookie 保存登录凭证,比较推荐由后端设置:
Set-Cookie: session_id=...; HttpOnly; Secure; SameSite=Lax这样前端 JavaScript 读不到 Cookie,可以降低令牌被脚本直接偷走的风险。
如果把 token 放在 localStorage:
localStorage.setItem("token", token);使用起来很方便,前端可以主动加请求头:
Authorization: Bearer token但它会暴露给页面脚本。只要出现 XSS,风险就会变高。
所以我现在更倾向于这样理解:
不是 localStorage 绝对不能放 token,
而是放之前要明确接受 XSS 带来的风险,并做好防护。如果是安全要求更高的系统,登录凭证优先考虑 HttpOnly Cookie。
不要把它们当数据库
这几种存储都适合放少量数据。
不要往里面塞大量列表、图片、复杂缓存或长期业务数据。
如果真的要做离线缓存、本地数据库、复杂查询,应该考虑:
IndexedDBCookie、localStorage、sessionStorage 更像是浏览器给我们的小抽屉,不是仓库。
我最后记住的判断方式
以后再选择存储方式时,可以先问几个问题:
- 服务器每次请求都需要它吗?
- 关闭标签页后还需要它吗?
- 它是不是敏感信息?
- 它是不是只属于当前页面流程?
- 它的数据量会不会变得很大?
如果服务器需要自动识别,就考虑 Cookie。
如果是长期前端偏好,就考虑 localStorage。
如果只是当前标签页的临时状态,就考虑 sessionStorage。
如果是高敏感登录凭证,要优先考虑安全属性,而不是只看写代码方不方便。