Token 存 localStorage 安全吗?为什么登录后还能被 CSRF 攻击?

Zz艺硕 阅读 17

我最近在做登录功能,后端返回的 token 我直接存到了 localStorage 里,每次请求手动加到 Authorization 头。但听说这样容易被 XSS 拿走,而且好像还是防不住 CSRF?有点懵。

比如我现在这个登录后的页面,会自动发个请求获取用户信息:

fetch('/api/user', {
  headers: {
    'Authorization': 'Bearer ' + localStorage.getItem('token')
  }
})

但同事说如果网站有 XSS 漏洞,攻击者就能读取 localStorage;而如果用 Cookie 存 token 又可能被 CSRF 利用。到底该怎么存才安全?有没有兼顾的办法?

我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
百里国娟
localStorage 存 token 确实有 XSS 风险,这个没跑。攻击者只要在你的页面上执行一段 JS,就能轻松把 localStorage 里的 token 拿走,因为 localStorage 对 JS 是完全开放的。

但你说防不住 CSRF,这事儿得分情况看。你现在用的是 Authorization 头手动加 token,这种方式其实不太容易被 CSRF 攻击,因为恶意页面没办法自动设置 Authorization 头——它又读不到你的 localStorage。CSRF 能成功利用的是浏览器会自动带上 Cookie 这个特性,跟 Authorization 头没关系。

你同事说的"Cookie 存 token 会被 CSRF 利用",指的是把 token 存到 Cookie 里,然后靠 Cookie 自动发送来完成认证这种情况。这种情况下确实存在 CSRF 风险,因为浏览器会自动把 Cookie 带到跨域请求里。

那怎么兼顾?业界常见的做法是:

token 存 Cookie 里,但要设置 SameSite 属性。SameSite=Strict 最安全,完全禁止跨域带 Cookie;SameSite=Lax 允许部分 GET 请求带 Cookie,但 POST 这种会限制。如果用 SameSite=Strict,基本就能挡住大多数 CSRF 攻击了。

如果觉得 SameSite=Lax 不够用,还可以再搭配一个 CSRF Token。后端生成一个随机 token,存到 Cookie 里(不设置 SameSite,或者设置为 Lax),然后前端在请求时从 Cookie 读取这个值,放到自定义头或者请求体里。后端同时验证 token 和 Referer,这样就更稳妥。

还有个常见的 Double Submit 模式:CSRF Token 既存在 Cookie 里,也存在请求参数或头里,后端比对两者是否一致。这种不需要服务端存储,适合分布式场景。

简单总结一下:localStorage + Authorization 头这种方式,XSS 风险大,但 CSRF 风险相对小;Cookie + SameSite + CSRF Token 这种组合能兼顾两边。你现在如果想改,可以考虑把 token 存 Cookie,设置 SameSite=Strict,再配个 CSRF Token,这样基本就稳了。
点赞
2026-03-19 22:03