前端鉴权实战:Token 存哪、怎么刷新、怎么防 XSS 与 CSRF

前端鉴权实战:Token 存哪、怎么刷新、怎么防 XSS 与 CSRF

“localStorage 里存 token 有 XSS 风险,那放 cookie 就安全了”——错,CSRF 在等着。

前后端分离项目的鉴权方案,网上一搜全是互相矛盾的答案。这篇不讲理论推演,直接给结论和落地代码:Token 放哪、过期怎么无感刷新、XSS 和 CSRF 各自怎么防。这套方案我用在一个有支付功能的项目里,安全评审一次过。

一、先分清两个威胁,方案才不纠结

威胁攻击者怎么拿/用你的凭证防御核心
XSS注入脚本在你的页面上下文里执行,能读 JS 能读的一切CSP、不把 token 放 JS 可读的地方、输入输出转义
CSRF恶意网站诱导浏览器自动携带 cookie 发请求(不需要读任何数据)Cookie SameSite、CSRF Token

记住这句就够:XSS 防的是"读走",CSRF 防的是"带上"。Token 放 localStorage 能防 CSRF(恶意站读不到),但挡不住 XSS;放 cookie 防得住"读走"(httpOnly),但要防 CSRF。没有银弹,是组合拳。

二、我的推荐架构:双 Token + httpOnly Cookie

Access Token(短期,15 分钟)  → 内存中持有,Authorization 头发送
Refresh Token(长期,7~30 天) → httpOnly + Secure + SameSite=Strict cookie

为什么这么分:

  • Access Token 放内存:刷新页面就没了,XSS 读到了也只有 15 分钟寿命,且不参与 CSRF(自定义请求头天然免疫,跨站表单带不上它)。
  • Refresh Token 放 httpOnly cookie:JS 读不到,XSS 偷不走;只发往 /auth/refresh 一个接口,攻击面被锁死;SameSite=Strict 让跨站请求根本不携带它,CSRF 无从谈起。

后端设置 refresh cookie 的关键属性(Express 示例):

res.cookie("refresh_token", token, {
  httpOnly: true,                  // JS 不可读
  secure: true,                    // 仅 HTTPS
  sameSite: "strict",              // 跨站请求不携带
  path: "/auth/refresh",           // 只在这个路径发送,缩小暴露面
  maxAge: 7 * 24 * 3600 * 1000,
});

path 这一手经常被忽略:refresh token 只需要给刷新接口用,限定 path 后,其他任何请求(包括被 XSS 劫持的请求)都带不上它。

三、无感刷新:用户永远不该看到"请重新登录"

Access Token 15 分钟过期,如果用户被打断到登录页,产品体验就崩了。标准解法:请求拦截器发现 401 → 用 refresh token 换新 token → 重放原请求。Axios 实现:

let refreshing: Promise<string> | null = null;

api.interceptors.response.use(undefined, async (error) => {
  if (error.response?.status !== 401 || isRetry(error.config)) throw error;

  refreshing ??= refreshToken().finally(() => (refreshing = null)); // 并发只刷一次
  const newToken = await refreshing;                                 // 所有请求等同一个结果
  error.config.headers.Authorization = `Bearer ${newToken}`;
  error.config._retried = true;
  return api(error.config);                                          // 重放原请求
});

两个必须处理的细节:

  1. 并发去重:页面一进来发 8 个请求,token 恰好过期,8 个 401 同时到。不去做并发合并,就会发起 8 次刷新、7 次因 refresh token 被轮换而失败、用户被登出。refreshing ??= ... 保证整页只有一个刷新请求,大家等同一个 Promise。
  2. 刷新也失败:refresh token 过期/被吊销,此时清状态、跳登录,并把用户当前页面的 URL 存下来(sessionStorage.redirect = location.href),登录后跳回去。这个"登回原页面"的小细节,留存率差异很明显。

后端配套:refresh token 每次使用后轮换(旧的作废、发新的),并在数据库记录"设备会话"。同一个 refresh token 被第二次使用 = 可能被偷了,直接吊销整个会话。这是 OWASP 推荐的 refresh token rotation。

四、XSS 防御:鉴权方案只是兜底

Token 放内存只是降低损失,XSS 本身还要正面防:

  1. 不拼接 HTML。React/Vue 默认转义插值,dangerouslySetInnerHTML/v-html 只允许出现在内容经过 DOMPurify 消毒的地方。
  2. CSP 收紧Content-Security-Policy: default-src 'self'; script-src 'self'。禁掉 inline script 和可疑外域,XSS 载荷大多数直接没法加载。注意用了 inline 事件或 JSON.pARSE 水合的要配 nonce。
  3. 依赖也是攻击面:npm 投毒事件真实发生过,lock 文件提交、CI 用 npm ci、定期 npm audit
  4. 别在 URL、日志里带 token:token 出现在 query string 会进各种访问日志。

五、CSRF:用对了 SameSite,传统 CSRF Token 可以省

CSRF 的成立条件是"浏览器自动携带凭证发跨站请求"。逐条拆解我们的方案:

  • 核心写接口用 Authorization 头 → 跨站表单/图片请求带不上,天然免疫。
  • refresh cookie 是 SameSite=Strict → 跨站请求根本不携带,免疫。
  • 如果站点必须兼容老浏览器、或 refresh cookie 用了 SameSite=Lax,再补一层 CSRF Token(后端下发随机值,写请求带头携带,服务端校验)。Lax 下跨站 POST 不带 cookie,但顶级导航的 GET 会带,所以GET 永远不要有副作用——这条比任何 token 都重要。

六、登出与"记住我":两个容易做错的点

登出不是删前端 token 就完了。后端必须吊销:access token 短命可以等它自然过期,refresh token 必须立即从会话表删除(或加黑名单)。否则"登出"只是前端表演,偷到 token 的人照用 7 天。

"记住我"的正确实现是延长 refresh token 有效期(7 天 → 30 天),而不是延长 access token。见过把 access token 直接设 30 天的项目,等于把最容易被偷的凭证做成了长期凭证,前面所有努力白费。

七、总结

把整套方案压成一张决策表:

问题答案
Access Token 放哪内存,15 分钟,Authorization 头
Refresh Token 放哪httpOnly + Secure + SameSite=Strict + 限定 path 的 cookie
过期怎么办拦截器 401 → 并发合并的无感刷新 → 重放请求
refresh 怎么防偷每次轮换 + 二次使用即吊销会话
XSS输出转义 + CSP + 依赖审计(token 方案只是降损)
CSRF自定义头免疫 + SameSite=Strict,GET 永远无副作用

按这张表把现有项目对一遍,重点检查三处:refresh token 是不是也在 localStorage 里(最常见的错)、401 并发刷新有没有合并、登出有没有吊销后端会话。

大气污染是影响公众健康生态环境的重要问题,精准的空气质量时空预测污染源贡献度量化是精准治污的关键支撑。针对现有研究多源融合不充分、时空关联刻画不足、预测源解析割裂三方面缺陷,本文设计实现了城市空气质量时空预测污染源贡献度分析系统,融合监测、气象、工业排放交通四类数据,构建基于时空注意力的LSTM(STAM-LSTM)预测模型基于正定矩阵因子分解(PMF)的源解析模型,形成数据融合-特征工程-预测-源解析-可视化闭环。 系统实现四类数据时空对齐融合,构建时序空间邻域特征,以普通克里金插值生成1km网格浓度场;STAM-LSTM引入时空注意力自适应学习站点间污染传输时变重,以72小时输入预测未来24小时逐小时PM2.5浓度;PMF识别交通、工业、燃煤、扬尘二次生成五个源因子,量化各源全年贡献度并分析时空演变。 实验表明:STAM-LSTM预测RMSE 24.6、MAE 17.8、R² 0.88,相对LSTM基线(30.2)提升18.5%;普通克里金插值误差8.9,优于反距离加(11.4);源解析显示交通源28.4%、工业源23.1%、燃煤源19.6%为主要贡献源,冬季燃煤源升至27.3%、早高峰交通源达34.8%,下风向工业源贡献高出上风向8~12个百分点;减排情景显示交通源减排20%可使年均PM2.5下降5.7%,源贡献度排序一致。 系统按五模块14组件实现,功能测试16项用例全部通过,为大气污染预警、源管控减排政策制定提供了决策依据。 【课程报告内容】 摘要 第1章 绪论 第2章 相关技术理论 第3章 系统需求分析 第4章 系统总体设计 第5章 系统详细设计实现 第6章 系统测试分析 第7章 总结展望 参考文献 附件-实现指南
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值