localStorage、sessionStorage 和 Cookie 的区别与使用场景

localStorage、sessionStorage 和 Cookie 的区别在哪?本文从 7 个实际项目场景出发,讲清楚什么时候用哪个,以及开发中容易踩的坑。

前端三大存储方案:各有什么本事

做前端开发,经常要面对一个问题:数据存哪儿。localStorage、sessionStorage 和 Cookie 三个选项摆在面前,长得像但脾气完全不一样。选错了,轻则功能异常,重则安全翻车。这篇文章把它们的区别、适用场景和坑都梳理一遍,重点说说实际项目中怎么选。

先看一张速查表

特性 Cookie localStorage sessionStorage
容量 4KB 左右 5MB+ 5MB+
过期时间 可设置 expires/max-age 永久,除非手动删除 关闭标签页后自动清除
是否随请求发送 是,自动带到 HTTP Header
作用域 同域名 + 可指定 path 同源(协议+域名+端口) 同标签页 + 同源
API 易用性 差,需手动拼接 好,setItem/getItem 好,与 localStorage 相同 API
服务端可设置 是,Set-Cookie
线程安全 天然异步边界 同步,会阻塞主线程 同步,会阻塞主线程

Cookie:最老但最特殊的存在

Cookie 诞生于 1994 年,NetScape 给浏览器设计出来的,初衷是让服务器能记住用户。它有两个核心特点其他存储方案没有:自动携带和过期可控。

每次请求同域名的接口,浏览器会自动把 Cookie 塞进 HTTP Header——登录态 token、会话 ID 这类需要服务端验证的数据,天然适合放 Cookie。这也是 Cookie 和另外两个最大的区别:它不只是前端存储,更是前后端通信的一部分。

场景一:登录态保持

用户登录后,后端返回一个 sessionId 或 JWT。最简单粗暴的做法是前端存 localStorage,每次请求从 localStorage 取出来拼到 Authorization header 里发出去。这种做法在 SPA 里很常见,但是有个致命问题:XSS 漏洞下攻击者可以 document.cookie 一样读不到 httpOnly 的 Cookie,但可以轻松读到 localStorage。

正确做法是把登录 token 放在 Cookie 里,设置 httpOnly 和 Secure 标志。这样前端 JS 完全碰不到这个 token,XSS 攻击者也没办法读走。后端通过 Cookie 解析 session,前端只管发请求。Cookie 的 4KB 空间对 token 来说绰绰有余。

实际项目中遇到过的问题是:跨子域名共享登录态。主站 login.example.com 登录后,用户在 app.example.com 也需要有登录态。Cookie 可以通过设置 domain=.example.com 来实现子域名共享。localStorage 做不到这一点,严格按源隔离,子域名之间互不相通。

场景二:多步骤表单暂存

一个典型的电商下单流程:选择商品 -> 填写地址 -> 选择支付方式 -> 确认订单 -> 支付。四五个步骤,用户可能每一步都要花时间填写,中间不小心刷新了页面怎么办?

sessionStorage 最适合这个场景。用户在第一步填写的信息实时保存到 sessionStorage,刷新不会丢,关闭页面自动清空——正好不需要永久保留。如果用 localStorage,用户下次打开浏览器还残留着上次的草稿,反而造成混乱。

另一个实际场景是富文本编辑器。写文章写到一半,防刷新丢失是很基本的需求。用 sessionStorage 做实时保存草稿,用户提交成功后再 removeItem 清理掉。用 localStorage 也行,但需要加时间戳和版本号避免残留数据污染。

场景三:用户偏好设置

网站的主题色(深色/浅色)、语言选择、列表展示模式(卡片/列表)、字体大小——这些用户偏好需要跨会话保留,但服务端不需要知道。

localStorage 是最合适的选择。数据永久保存,除非用户主动清缓存或用代码删除。API 简单,getItem/setItem 两行代码搞定。不需要像 Cookie 那样每次请求都带着跑,节省带宽。

实际开发中常见的一个坑:切换主题时用 localStorage 存一个 dark 或 light 字符串,但用户清除了浏览器缓存后主题重置,页面闪烁。解决方案是在 HTML 的 head 里用阻塞脚本先读 localStorage,在页面渲染前把主题 class 加到 html 元素上,避免亮白屏一闪。

场景四:页面间传参

从一个页面跳到另一个页面,带些参数过去。URL 传参是最直白的,但参数暴露在地址栏里,不安全也不美观。尤其是金额、订单号这类敏感参数,暴露在 URL 里用户复制链接分享出去就泄露了。

sessionStorage 可以解决这个问题。A 页面把参数写进 sessionStorage,B 页面在同标签页下读取。刷新不丢失,关闭标签页自动清空,参数不会暴露在 URL 里。要注意的是 sessionStorage 只在当前标签页有效——新开标签页是不共享的。如果需要在不同标签页之间共享,得用 localStorage 或者 BroadcastChannel API。

场景五:无痕浏览与隐私保护

某些功能需要在用户退出后彻底清除数据,比如在线考试系统、银行网银的临时操作记录。用 Cookie 的话服务端还得发清除指令,用 localStorage 的话开发者要手动删除,漏删了就留下痕迹。

sessionStorage 在这个场景下是天然的解决方案。用户关掉标签页或浏览器,所有数据自动消失。不需要写额外的清理代码。配合页面 unload 事件主动清除,做到双重保险。

场景六:服务端下发的前端配置

有些配置需要在后端控制,比如某个功能开关、AB 实验分组、弹窗展示策略。后端返回 HTML 时通过 Set-Cookie 写入 Cookie,前端 JS 可以直接读 document.cookie 取出来用。

和 localStorage 方案相比,Cookie 的好处是不需要额外发一个 API 请求来获取配置——后端在响应里顺手就带上了。缺点是 4KB 容量限制,太大块的数据不适合放 Cookie。实际情况中 CDN 缓存静态页面的场景下,Cookie 会导致缓存失效,这种情况更推荐通过独立接口返回配置,前端存到 localStorage 里。

场景七:监控和埋点

用户访问埋点、页面停留时长、点击热力图——这些数据通常需要暂存一批然后批量上报。

用 Cookie 肯定不合适,4KB 的容量加上每次请求都携带,浪费带宽。localStorage 是主流方案:埋点数据累积到一定数量或一定时间后,通过一个独立的请求批量上报,上报成功后清理 localStorage 里的数据。sessionStorage 也可以做短期埋点缓存,但如果用户关了页面还没上报的数据就丢了,需要配合 beforeunload 事件做最后的上报尝试。

安全注意事项

localStorage 和 sessionStorage 没有 httpOnly 标志,页面中任何 JavaScript 都能读取。一旦站点存在 XSS 漏洞,攻击者可以轻松窃取里面存储的 token 或用户数据。不要把 JWT、支付密钥、身份证号等信息放在 localStorage 里。

Cookie 设置了 httpOnly 后 JS 无法读写,XSS 窃取不了。但 Cookie 存在 CSRF 风险,需要用 SameSite 属性、CSRF Token 或自定义请求头来防护。SameSite=Lax 是现在浏览器的默认行为,基本覆盖了大部分场景。

还有一个容易忽略的点:localStorage 在隐私模式/无痕模式下某些浏览器表现不一致。Safari 的无痕模式下 localStorage 可用但数据在标签页关闭后清除。部分旧版浏览器在无痕模式下写入 localStorage 会直接抛异常。用之前最好 try-catch 兜一下。

总结

Cookie 适合服务端需要读取的敏感数据,登录态的场景首选。localStorage 适合长期持久化的客户端配置,主题色、语言偏好这类放进去。sessionStorage 适合临时的页面级数据,表单草稿、页面传参、临时缓存都用它。

选型逻辑很简单:服务端要读吗?要 -> Cookie。要跨会话保留吗?要 -> localStorage。只是当前会话有效?-> sessionStorage。这个判断链能覆盖 90% 以上的场景。另外不管用哪个,敏感数据别往客户端存就对了——真需要安全,走 httpOnly Cookie。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注