SPA-API通信中Anti-CSRF Token的工作原理及误解解析
关于SPA-API通信中Anti-CSRF Token的工作原理及常见误解澄清
首先要明确CSRF攻击的核心本质:攻击者利用浏览器的同源策略特性——发起跨域请求时,浏览器会自动携带目标域名下的Cookie,但攻击者无法读取/修改这些Cookie,也无法访问目标域名下的localStorage/sessionStorage。你的疑惑大多源于对这个核心点的误解。
一、SPA中正确的Anti-CSRF Token实现流程
正确的安全实现并非你理解的简化流程,完整逻辑应该是:
- 用户登录时,服务器返回两个关键内容:
- 一个设置了
HttpOnly、SameSite=Strict/Lax的会话Cookie(比如session_id),用于标识用户身份,浏览器会自动携带这个Cookie。 - 一个独立的CSRF Token,通过响应体(比如JSON字段
csrf_token)返回给前端。
- 前端将CSRF Token存储在
sessionStorage或localStorage中(也可存在非HttpOnly的Cookie里,但Web Storage是更常见的选择)。
- 前端将CSRF Token存储在
- 后续发起非GET类请求(POST/PUT/DELETE等,这类请求通常会修改服务器状态,CSRF风险更高)时,前端主动从存储中取出Token,放在请求头(比如
X-CSRF-Token)或请求体里一并发送。
- 后续发起非GET类请求(POST/PUT/DELETE等,这类请求通常会修改服务器状态,CSRF风险更高)时,前端主动从存储中取出Token,放在请求头(比如
- 服务器验证逻辑:
- 先通过Cookie中的
session_id找到对应的用户会话。 - 再检查请求头/体中的CSRF Token,是否与该用户会话中存储的Token一致,只有匹配才会处理请求。
二、为什么这样能防范CSRF?
针对你提出的存储位置疑问,逐一拆解:
- Token存在Web Storage:攻击者的跨域站点无法通过JavaScript读取目标域名下的Web Storage(同源策略严格限制跨域存储访问),所以诱导用户发起的伪造请求中,无法携带正确的CSRF Token,服务器会直接拒绝。
- Token存在非HttpOnly的Cookie:同样,攻击者的跨域JS无法读取目标域名的Cookie,自然拿不到Token。前端可以通过
document.cookie读取这个Token并主动携带到请求中,而攻击者伪造的请求做不到这一点。
你之前的误区在于:误以为攻击者的JS能访问用户浏览器中目标站点的存储内容,但同源策略从根本上阻止了这种跨域访问。
三、Anti-CSRF Token与普通认证Cookie的差异
| 维度 | Anti-CSRF Token | 普通认证Cookie(如session_id) |
|---|---|---|
| 核心作用 | 验证请求合法性:证明请求是用户主动发起,而非伪造 | 验证用户身份:证明“当前请求发起者是哪个用户” |
| 传递方式 | 必须由前端主动在请求头/体中携带,不会自动发送 | 浏览器会自动在同源请求中携带,无需前端额外处理 |
| 存储安全要求 | 可存在Web Storage或非HttpOnly Cookie(存在XSS风险,但XSS属于另一类攻击,需单独防护) | 建议设置HttpOnly、SameSite=Strict/Lax,防止被XSS窃取 |
| 生命周期 | 通常与会话绑定,会话结束后失效 | 与会话生命周期一致,或可设置持久化过期时间 |
总结你的误解点
- 忽略了同源策略对跨域存储访问的限制:攻击者的站点无法获取目标站点的任何存储内容(Cookie、Web Storage),因此拿不到CSRF Token。
- 混淆了两类凭证的作用:CSRF Token是“请求合法性凭证”,认证Cookie是“用户身份凭证”,二者配合才能同时实现身份认证和CSRF防护。
内容的提问来源于stack exchange,提问作者Nullable Yogurt
相关产品推荐
相关产品推荐

