前端基础

从 Cookie 到 localStorage 理解浏览器本地存储

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

2026年6月13日8 分钟阅读
从 Cookie 到 localStorage 理解浏览器本地存储

这篇笔记记录一下我对浏览器里几种常见本地存储方式的理解。

一开始我经常把这些名字混在一起:

text
Cookie
sessionStorage
localStorage

它们看起来都能在浏览器里保存一点数据,但生命周期、是否会自动发送给服务器、适合放什么东西,其实差别很大。

后来我发现,可以先抓住一个问题:

text
这份数据是给服务器看的,还是只给前端自己用的?

再继续看它需要保存多久、是否只属于当前标签页、是否涉及安全信息。

先说结论

可以先记住几句话:

  1. Cookie 会随着符合条件的 HTTP 请求自动发送给服务器。
  2. localStorage 主要给前端长期保存少量数据,除非手动删除,否则一般会一直存在。
  3. sessionStorage 只在当前标签页会话中存在,关闭标签页后通常就没了。
  4. Cookie 适合保存服务器需要识别的状态,比如登录凭证,但要认真设置安全属性。
  5. localStorage 和 sessionStorage 适合保存前端状态,不适合保存高敏感凭证。
  6. 三者容量都不适合放大量数据,复杂离线数据更适合考虑 IndexedDB。

如果用一句话粗略区分:

text
Cookie 偏服务端通信,localStorage 和 sessionStorage 偏前端本地状态。

Cookie 是浏览器保存的一小段键值数据。

服务端可以通过响应头告诉浏览器保存 Cookie:

http
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Lax

之后浏览器访问同一个站点里符合条件的接口时,会自动带上:

http
Cookie: session_id=abc123

这就是 Cookie 和另外两种存储最大的区别。

localStorage 和 sessionStorage 只是放在浏览器里,默认不会跟着请求走。Cookie 则天然参与 HTTP 请求。

Cookie 的生命周期主要看有没有设置过期时间。

如果没有设置 ExpiresMax-Age,它通常是会话 Cookie。浏览器会话结束后可能被清理。

http
Set-Cookie: session_id=abc123

如果设置了 Max-Age

http
Set-Cookie: token=abc123; Max-Age=86400

表示 Cookie 最多保存 86400 秒。

如果设置了 Expires

http
Set-Cookie: token=abc123; Expires=Wed, 10 Jun 2026 10:00:00 GMT

表示到指定时间后过期。

实际项目里,我更喜欢把登录态 Cookie 的过期时间和后端会话或令牌有效期一起设计,不要让前端以为自己还登录着,后端却已经不认了。

Cookie 常见用在这些地方:

  • 保存 Session ID。
  • 保存刷新令牌或登录凭证。
  • 记录灰度发布、A/B 测试分组。
  • 保存语言、地区等服务端也需要读取的偏好。
  • 做一些简单的跨页面状态识别。

如果后端需要在每次请求时识别用户,Cookie 很自然。

例如传统 Session 登录里,浏览器保存的是:

text
session_id=abc123

服务器根据这个 ID 去自己的存储里查当前用户是谁。

Cookie 好用,但也容易出安全问题。

HttpOnly

http
Set-Cookie: session_id=abc123; HttpOnly

设置以后,前端 JavaScript 不能通过 document.cookie 读取它。

这对登录凭证很重要。即使页面里出现 XSS 漏洞,攻击者也更难直接偷走 Cookie 内容。

Secure

http
Set-Cookie: session_id=abc123; Secure

表示只在 HTTPS 请求中发送。

正式环境里的登录 Cookie 通常都应该设置。

SameSite

http
Set-Cookie: session_id=abc123; SameSite=Lax

它主要用来减少 CSRF 风险。

常见值有:

大概含义
Strict跨站场景基本不发送
Lax常见跳转场景可以发送,跨站表单等场景受限
None跨站也发送,但通常必须配合 Secure

如果是普通后台系统,Lax 经常是比较稳的默认选择。

localStorage 是什么

localStorage 是浏览器提供给前端的一种持久化键值存储。

写入:

ts
localStorage.setItem("theme", "dark");

读取:

ts
const theme = localStorage.getItem("theme");

删除:

ts
localStorage.removeItem("theme");

它只能保存字符串。如果要保存对象,需要自己序列化:

ts
localStorage.setItem("userSettings", JSON.stringify(settings));

读取时再解析:

ts
const settings = JSON.parse(
  localStorage.getItem("userSettings") ?? "{}",
);

localStorage 的生命周期

localStorage 没有默认过期时间。

只要用户不主动清理浏览器数据,或者代码不手动删除,它通常会一直存在。

这很适合保存一些长期偏好:

  • 主题模式。
  • 语言偏好。
  • 侧边栏是否折叠。
  • 表格列配置。
  • 最近使用的筛选条件。
  • 本地草稿。

但也正因为它保存得久,不适合随便放敏感信息。

sessionStorage 是什么

sessionStorage 的 API 和 localStorage 很像:

ts
sessionStorage.setItem("step", "2");
const step = sessionStorage.getItem("step");

区别在生命周期和作用范围。

sessionStorage 通常只属于当前标签页。

同一个网站打开两个标签页,它们的 sessionStorage 一般不是同一份。关闭标签页后,这份数据也会被清掉。

sessionStorage 的应用场景

sessionStorage 适合保存只和当前页面流程有关的数据:

  • 多步骤表单的临时步骤。
  • 当前标签页里的临时搜索条件。
  • 支付或授权跳转前后的短暂状态。
  • 防止刷新后丢失的页面临时数据。

例如一个三步表单,用户刷新页面时不想从第一步重新开始,可以把当前步骤暂时保存到 sessionStorage。

ts
sessionStorage.setItem("createOrderStep", String(currentStep));

但是关闭标签页以后,这个状态就不需要继续保留了。

三者对比

可以用一张表记住:

对比项CookielocalStoragesessionStorage
是否自动随请求发送不会不会
主要使用方前端和服务端前端前端
生命周期可配置,或浏览器会话通常长期保存当前标签页会话
容量较小比 Cookie 大比 Cookie 大
适合保存登录标识、服务端需要的状态长期前端偏好临时页面状态
JS 能否读取取决于 HttpOnly可以可以

登录信息到底放哪里

这个问题很常见。

如果使用 Cookie 保存登录凭证,比较推荐由后端设置:

http
Set-Cookie: session_id=...; HttpOnly; Secure; SameSite=Lax

这样前端 JavaScript 读不到 Cookie,可以降低令牌被脚本直接偷走的风险。

如果把 token 放在 localStorage:

ts
localStorage.setItem("token", token);

使用起来很方便,前端可以主动加请求头:

ts
Authorization: Bearer token

但它会暴露给页面脚本。只要出现 XSS,风险就会变高。

所以我现在更倾向于这样理解:

text
不是 localStorage 绝对不能放 token,
而是放之前要明确接受 XSS 带来的风险,并做好防护。

如果是安全要求更高的系统,登录凭证优先考虑 HttpOnly Cookie。

不要把它们当数据库

这几种存储都适合放少量数据。

不要往里面塞大量列表、图片、复杂缓存或长期业务数据。

如果真的要做离线缓存、本地数据库、复杂查询,应该考虑:

text
IndexedDB

Cookie、localStorage、sessionStorage 更像是浏览器给我们的小抽屉,不是仓库。

我最后记住的判断方式

以后再选择存储方式时,可以先问几个问题:

  1. 服务器每次请求都需要它吗?
  2. 关闭标签页后还需要它吗?
  3. 它是不是敏感信息?
  4. 它是不是只属于当前页面流程?
  5. 它的数据量会不会变得很大?

如果服务器需要自动识别,就考虑 Cookie。

如果是长期前端偏好,就考虑 localStorage。

如果只是当前标签页的临时状态,就考虑 sessionStorage。

如果是高敏感登录凭证,要优先考虑安全属性,而不是只看写代码方不方便。