一、CSRF 的工作原理
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种攻击方式,攻击者诱导用户在已登录目标网站的情况下,向该网站发送恶意请求,利用用户的身份凭证(如 Cookie)执行非预期操作(如转账、修改密码等)。
核心原理:
1.用户登录目标网站 A,网站 A 生成并存储用户的身份凭证(如 Session Cookie),浏览器保留该 Cookie。
2.攻击者诱导用户在未退出网站 A 的情况下,访问恶意网站 B(或点击包含恶意代码的链接)。
3.恶意网站 B 向网站 A 发送一个伪造的请求(如 POST /transfer),该请求会自动携带用户在网站 A 的 Cookie(浏览器的同源策略允许跨站请求携带 Cookie)。
4.网站 A 收到请求后,验证 Cookie 有效,误认为是用户本人操作,从而执行恶意请求。
示例场景:
用户登录银行网站后,被诱导点击一封邮件中的链接,该链接指向恶意网站,后者自动向银行发送 POST /transfer?to=攻击者账户&amount=1000
请求,由于浏览器自动携带银行 Cookie,银行会执行转账操作。
二、CSRF 与 XSS 的主要区别
维度 | CSRF | XSS |
攻击目标 | 利用用户的身份执行未授权操作(如修改数据) | 注入恶意脚本窃取信息或控制用户会话 |
技术核心 | 伪造跨站请求,依赖用户已登录状态 | 突破浏览器限制,执行恶意代码 |
与用户交互 | 无需用户输入,依赖诱导点击或自动请求 | 需将恶意脚本注入到目标网站并被执行 |
防御重点 | 验证请求来源的合法性(如 Token、SameSite) | 过滤 / 转义用户输入,防止脚本执行 |
三、通过 SameSite Cookie 属性防御 CSRF
SameSite 是 Cookie 的属性之一,用于限制跨站请求时 Cookie 的发送行为,从而阻断 CSRF 攻击中 Cookie 的自动携带。
1. 作用机制
当 Cookie 设置 SameSite 属性后,浏览器在跨站请求时会根据属性值决定是否携带该 Cookie,避免恶意网站利用用户的登录状态发起请求。
- 当 Cookie 设置 SameSite 属性后,浏览器在跨站请求时会根据属性值决定是否携带该 Cookie,避免恶意网站利用用户的登录状态发起请求。
2. 不同取值(Strict/Lax)的适用场景
SameSite=Strict:
- 规则:完全禁止跨站请求携带 Cookie。只有当请求的来源与目标网站完全同源(协议、域名、端口一致)时,Cookie 才会被携带。
- 适用场景:安全性要求极高的操作,如支付、修改密码、转账等。例如,银行网站的核心功能需严格限制跨站请求,防止任何跨站场景下的身份滥用。
SameSite=Lax:
- 规则:允许部分安全的跨站请求携带 Cookie,仅在 “导航类” 跨站请求(如点击链接 <a>、提交表单 <form>)中携带,禁止通过 XMLHttpRequest、fetch 等脚本发起的跨站请求携带。
- 适用场景:兼顾安全性和用户体验的通用场景,如社交网站的分享功能(用户从第三方网站点击链接跳转回平台时,需携带登录状态)、电商网站的商品跳转等。大多数网站默认使用 Lax,平衡安全与可用性。
四、SPA 中结合 CSRF Token 与 CORS 策略实现跨域请求安全
SPA(单页应用)通常通过 AJAX 与后端跨域通信,需同时利用 CSRF Token(验证请求合法性)和 CORS(限制跨域权限)保障安全。
1. 核心思路
- CSRF Token:后端为每个会话生成唯一 Token,要求前端请求时携带,后端验证 Token 有效性,确保请求由用户主动发起。
- CORS:后端通过 HTTP 头限制允许的跨域来源、请求方法和 headers,防止未授权域名的跨域请求。
2. 具体实现步骤
步骤 1:后端生成并验证 CSRF Token
- 用户登录后,后端生成 CSRF Token(存储在 Session 或 Redis 中,与用户会话关联)。
- 前端通过接口(如 GET /csrf-token)获取 Token,存储在前端(如 localStorage 或内存中,不存储在 Cookie 中,避免被 CSRF 攻击利用)。
步骤 2:前端请求携带 Token
前端发起跨域请求(如 fetch
或 axios
)时,在请求头(如 X-CSRF-Token
)中携带 Token:
fetch('https://api.example.com/action', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': localStorage.getItem('csrfToken') // 从前端存储中获取
},
body: JSON.stringify({ data: 'xxx' })
});
步骤 3:后端配置 CORS 策略
后端通过 Access-Control-Allow-*
头限制跨域权限,例如:
Access-Control-Allow-Origin: https://spa.example.com # 仅允许可信前端域名
Access-Control-Allow-Methods: POST, GET, OPTIONS # 限制允许的请求方法
Access-Control-Allow-Headers: X-CSRF-Token, Content-Type # 允许携带 Token 头
Access-Control-Credentials: true # 允许跨域请求携带 Cookie(若需会话验证)
步骤 4:后端验证 Token 与 CORS
1.验证请求头中的 X-CSRF-Token 与后端存储的 Token 是否一致,不一致则拒绝请求。
2.检查请求来源是否在 Access-Control-Allow-Origin 列表中,不符合则拦截。
总结
- CSRF 利用用户身份凭证伪造请求,与 XSS 的核心区别在于是否依赖注入脚本。
- SameSite Cookie 通过限制跨站 Cookie 携带防御 CSRF,Strict 适用于高安全场景,Lax 兼顾体验。
- SPA 中需结合 CSRF Token(验证请求合法性)和 CORS(限制跨域范围),确保跨域请求的安全性。