CSRF 保护
规则
- 在所有 Cookie 上设置
SameSite=Lax——默认即可阻止大多数 CSRF 攻击
- 针对高度敏感的操作(如删除账户、更改密码)使用
SameSite=Strict
- 对自定义 API 实施双重提交 Cookie 模式:CSRF 令牌同时存在于 Cookie 和请求头中
- 在所有执行状态变更操作的 HTML 表单中包含 CSRF 令牌
- 在状态变更请求上验证
Origin 和 Referer 请求头,作为深度防御
- Next.js Server Actions 和 SvelteKit 表单操作会自动处理 CSRF —— 请使用它们
- 对于单页应用(SPA):在自定义请求头(
X-CSRF-Token)中发送 CSRF 令牌——浏览器默认会阻止跨域自定义请求头
import crypto from "crypto";
function generateCsrfToken(res) {
const token = crypto.randomBytes(32).toString("hex");
res.cookie("csrf_token", token, { httpOnly: false, sameSite: "strict", secure: true });
return token;
}
function verifyCsrf(req) {
const cookieToken = req.cookies.csrf_token;
const headerToken = req.headers["x-csrf-token"];
if (!cookieToken || cookieToken !== headerToken) {
throw new Error("CSRF validation failed");
}
}
避免
- 仅依赖基于 Cookie 的身份验证而没有 CSRF 保护——任何站点都可以向你的端点提交表单
- 使用永不轮换的 CSRF 令牌——一个令牌泄露将危及所有未来的请求
- 使用 GET 请求改变状态——CSRF 保护仅对 POST/PUT/DELETE 有效,因为 GET 请求会绕过
SameSite=Lax
- 因为“它只是一个 API”而禁用 CSRF 保护——如果涉及 Cookie,CSRF 就适用