使用独立后端API的Node.js单页应用如何防范XSRF攻击
前后端分离部署架构的XSRF防护实现方案
首先需要先完成基础跨域配置,这是所有防护方案生效的前提:
- 后端API服务关闭CORS通配符
*,仅允许你的前端静态资源服务域名跨域访问,同时开启credentials配置允许跨域携带Cookie - 前端所有发往后端的请求统一开启凭证携带:用axios的话配置
axios.defaults.withCredentials = true,用fetch的话配置credentials: 'include'
推荐方案:双Cookie校验模式(无需改造静态服务,适配纯前后端分离场景)
这是目前前后端分离架构下最通用的OWASP合规方案,不需要两个Node服务做数据同步,完全由后端API实现核心逻辑:
- 前端首次加载完成后,主动调用后端的
/api/csrf-init接口 - 后端接口生成一对关联值:1)明文CSRF令牌写入
HttpOnly: false、SameSite: Lax/Strict、Secure: 生产环境开启的Cookie,domain设置为两个服务的公共根域名;2)该令牌的加盐哈希值写入HttpOnly: true、同SameSite和Secure规则的另一个Cookie - 前端发起POST/PUT/DELETE等会修改数据的非幂等请求时,从Cookie中读取明文CSRF令牌,添加到自定义请求头(比如
X-CSRF-Token)中 - 后端收到请求后,取出请求头中的令牌,计算加盐哈希后和
HttpOnlyCookie中存储的哈希值做比对,一致则放行,不一致直接拦截返回403
该方案的核心逻辑是:CSRF攻击只能自动携带目标站点的Cookie,无法读取Cookie内容也无法自定义请求头,所以只有真实的前端应用才能从Cookie中拿到令牌并放到请求头中,天然抵御CSRF攻击。
备选方案:静态服务嵌入令牌(适合静态服务可做轻量SSR/HTML注入的场景)
如果你的React SPA静态服务可以在返回HTML时做内容注入,可以用这个更简单的方案:
- 用户请求前端静态HTML时,静态服务先向后端API申请单次有效的CSRF令牌
- 静态服务将令牌注入到HTML的meta标签中,比如
<meta name="csrf-token" content="生成的令牌值"> - React应用初始化时从meta标签读取令牌,后续所有请求都将令牌携带在自定义请求头中,后端直接做校验即可
通用安全加固规则
- 所有和CSRF、会话相关的Cookie必须开启
SameSite属性,优先设置为Strict,跨站跳转需求的场景设置为Lax,生产环境必须开启Secure属性仅允许HTTPS传输 - 不对GET/HEAD/OPTIONS这类幂等请求做CSRF校验,仅校验会修改服务端数据的请求
- CSRF令牌的有效期和用户登录会话有效期保持一致,用户登出时同步销毁令牌对应的校验数据
内容的提问来源于stack exchange,提问作者user2968425
相关产品推荐
相关产品推荐

