介绍
Cookie 是管理用户身份验证状态的便捷机制。当会话 ID 存储在 cookie 中时,浏览器会自动将其附加到针对该域的传出 HTTP 请求。
但是,此自动附件功能会被 跨站点请求伪造 (CSRF) 攻击所利用。
尽管现代浏览器默认采用更安全的 cookie 行为(例如自动应用 SameSite=Lax),但开发人员必须了解 CSRF 防御模式以防止严重的身份验证漏洞。本文回顾 SameSite cookie 属性和 CSRF 令牌验证模式。
1. CSRF 攻击如何运作
当恶意网站提示受害者的浏览器在用户当前经过身份验证的受信任应用程序上执行不需要的操作时,就会发生 CSRF 攻击。
- 用户登录银行应用程序 (
bank.com),服务器将会话标识符存储在本地 cookie 中。 - 经过身份验证后,用户访问恶意网站 (
evil.com)。 - 恶意站点运行一个脚本,将转账请求 (
POST /transfer) 发送到银行应用程序 (bank.com)。 - 由于请求的目标是
bank.com,浏览器会自动包含经过身份验证的会话 cookie。 - 银行服务器将请求作为合法的、经过身份验证的会话处理,并执行交易。
2.防御一:SameSite Cookie 属性
防止 CSRF 最有效的方法是将 SameSite 属性应用于会话 cookie。此设置告诉浏览器是否应将 cookie 包含在源自第三方(跨站点)域的请求中。
三种配置选项
Set-Cookie: sessionId=abc123; Secure; HttpOnly; SameSite=Lax
| 设置 | 行为 |
|---|---|
| SameSite=严格 | 阻止浏览器在跨站点请求中发送 cookie。即使用户从外部搜索引擎单击直接链接到您的网站,他们也需要再次登录,因为 cookie 被保留。 |
| SameSite=宽松 | 在跨站点请求上保留 cookie,但在用户通过单击链接(GET 请求)导航到您的站点时允许 cookie。这是 Web 应用程序的行业默认设置。 |
| SameSite=无 | 将 cookie 附加到所有跨站点请求,包括嵌入式 iframe 调用。设置 SameSite=None 需要 Secure 标志(限制传输到 HTTPS 连接)。 |
SameSite=Lax 的重要限制
虽然大多数现代浏览器默认使用 SameSite=Lax,但仅依赖它会留下潜在的安全漏洞:
- 不正确的 HTTP 方法使用(GET 突变):
如果您的应用程序通过 GET 请求(例如
GET /delete?id=5)执行状态更改,SameSite=Lax将不会保护您,因为 Lax 允许在跨站点 GET 链接点击时使用 cookie。对于状态更改端点,始终使用POST、PUT或DELETE。 - 旧版浏览器支持:
较旧的移动 WebView 环境和旧版桌面浏览器无法识别
SameSite属性。
3.防御2:双重提交Cookie模式
为了确保所有浏览器环境的安全性,应用程序应使用 CSRF 令牌 验证机制。无状态单页应用程序 (SPA) 的常见模式是 双提交 Cookie 模式。
它是如何运作的
- 当用户进行身份验证时,服务器会生成一个随机的加密安全令牌(CSRF 令牌)并将其存储为客户端 cookie。
- 当 SPA 发出变更请求(
POST、PUT、DELETE)时,JavaScript 会读取 cookie 值并将令牌附加到自定义 HTTP 标头(例如X-CSRF-Token)。 - 后端服务器验证请求头中的token与cookie中的token是否匹配。
为什么这是安全的
虽然恶意网站 (evil.com) 可以触发自动包含应用程序 cookie 的表单提交,但浏览器的 同源策略 (SOP) 会阻止第三方 JavaScript 读取您的 cookie 将令牌附加到自定义 HTTP 标头。
结论
保护您的身份验证管道免受 CSRF 的影响需要采用多层方法:
- 确保所有会话 cookie 均配置有
SameSite=Lax或Strict并包含HttpOnly标志。 - 绝不允许通过 GET 请求发生状态更改。
- 使用自定义 HTTP 标头和双重提交 Cookie 模式来保护突变端点。
实施这些准则将保护您的会话身份验证并保护用户免受劫持攻击。

