CSRF 防御实战:Token 与 Nginx 双重防护配置

适用场景

CSRF 攻击防御适用于所有基于 Cookie 会话的 Web 应用,包括管理后台、支付回调、用户资料修改等高风险操作。当应用仅依赖 Cookie 鉴权且无防护机制时,攻击者可诱导已登录用户发起恶意请求,造成改密、越权操作或数据篡改。本教程适用于 PHP/Java/Python 等主流 Web 应用及 Nginx 反向代理环境。

前置条件

  • 已部署的 Web 应用(示例基于 PHP + Nginx)
  • 服务器 root 权限(用于修改 Nginx 配置)
  • 应用支持 Session 与 Cookie 机制

原理说明

CSRF 攻击利用浏览器自动携带 Cookie 的特性:用户访问恶意页面时,页面中的表单或图片请求会自动携带目标站点的会话 Cookie,服务端无法区分请求是否由用户主动发起。防御核心是让服务端能够验证请求”来源可信”,常见手段包括同步 Token 校验SameSite Cookie 属性Referer 来源校验。同步 Token 是业界首选方案,因为它不依赖浏览器行为,兼容性最好。

操作步骤

第一步:应用层引入 CSRF Token

在表单中嵌入随机 Token 并存入 Session,提交时用 hash_equals 恒定时间比对:

<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
        http_response_code(403);
        exit('CSRF 校验失败');
    }
}
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
?>

表单中输出隐藏字段:<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">

第二步:设置 SameSite Cookie

setcookie('session_id', $sid, [
    'httponly' => true,
    'samesite' => 'Lax',
    'secure'   => true
]);

SameSite=Lax 阻止跨站请求携带 Cookie,Secure 强制 HTTPS 传输,HttpOnly 防 XSS 窃取。

第三步:Nginx 层校验 Referer(纵深防御)

location ~ ^/(admin|api)/ {
    if ($http_referer !~ "^https?://(www\.)?example\.com/") {
        return 403;
    }
    proxy_pass http://127.0.0.1:8080;
}

注意:仅校验 Referer 不足以防御(空 Referer 或同源 XSS 可绕过),必须与 Token 配合使用。

第四步:关键操作二次校验

对改密、删除等敏感操作增加二次确认(验证码或再次输入密码),进一步缩小攻击面。

配置验证

  • 正常流程:登录后提交表单,返回 200
  • 篡改 Token:手动修改表单 Token 值提交,应返回 403
  • 跨站模拟:curl -X POST https://example.com/admin/delete -H "Referer: https://evil.com",应返回 403
  • 检查响应头 Set-Cookie 是否包含 SameSite=Lax 属性

常见问题

Q1:Token 校验会影响所有 POST 请求吗?

只影响启用校验的接口。建议对登录后所有写操作统一校验,GET 请求无需校验但不得执行状态修改

Q2:前后端分离(SPA + API)如何防 CSRF?

使用 Authorization 请求头携带令牌(非 Cookie)即可天然免疫;若必须使用 Cookie,需配合 SameSite=Strict 或自定义请求头校验。

Q3:Nginx Referer 校验误伤合法请求怎么办?

只对写操作(POST/PUT/DELETE)与后台路径启用校验,GET 与静态资源不校验;同域多站点场景需在白名单中补充所有可信域名。

总结

CSRF 防御需分层实施:应用层同步 Token是根基,SameSite Cookie提供浏览器级兜底,Nginx Referer 校验作为纵深防御。三者结合可覆盖绝大多数 CSRF 攻击场景,建议在生产环境逐步启用并配合自动化安全测试回归验证。