Yii2 CSRF防护默认关闭,必须显式设enableCsrfValidation=true;需配置cookieValidationKey、表单嵌入csrfInput、AJAX带X-CSRF-Token头,并谨慎控制禁用范围。

Yii框架的CSRF防护默认是关的,enableCsrfValidation 必须显式设为 true,否则所有POST表单都裸奔——这不是“建议开启”,而是生产环境强制要求。
CSRF开关必须手动打开,且不能只配 request 组件
很多项目在 config/web.php 里写了 'enableCsrfValidation' => true 就以为万事大吉,结果上线后表单 400 报错。问题往往出在两处:
-
cookieValidationKey没设或设为空——它不是可选项,是CSRF令牌签名的密钥基础;留空等于用默认值(比如'test'),攻击者能本地伪造 token - 控制器里覆盖了配置:比如某 Controller 的
init()或beforeAction()中写了$this->enableCsrfValidation = false,却忘了注释说明,导致整个控制器失防 - 测试环境用了
'cookieValidationKey' => 'test',但没同步到生产,而生产又没配,结果 token 校验永远失败
表单里漏掉 csrfInput 就直接 400
Yii 不会自动给任意 补 CSRF 字段,只对用 Html::beginForm()、ActiveForm::begin() 生成的表单才注入 。手写原生 form 或用 JS 动态拼 DOM 时极易遗漏。
- 检查渲染后的 HTML 源码,确认是否存在
name="_csrf"的 hidden input(注意csrfParam可能被改过,默认是_csrf) - AJAX POST 请求必须手动带 token:fetch 提交时加
headers: { 'X-CSRF-Token': '...' },或 body 里塞_csrf: '...';别依赖前端 JS 自动读取 meta 标签——用户禁用 JS 后照样能发恶意请求 - GET 表单(如搜索框)不校验 CSRF,但若后端逻辑实际修改了状态(比如清购物车),就得主动调用
$request->validateCsrfToken(),不能因 method 是 GET 就放松警惕
动态禁用 CSRF 要小心作用域和继承关系
有些接口确实不该校验 CSRF(比如 Webhook 回调、第三方系统通知),但禁用方式不对会引发越界失效。
- 在控制器中用
public $enableCsrfValidation = false是全局禁用,整个 Controller 所有 action 都不校验——哪怕其中只有 1 个 action 需要开放 - 更安全的做法是在
beforeAction()里按 action ID 精确控制:if ($action->id === 'webhook') { $this->enableCsrfValidation = false; } - 注意继承链:如果父 Controller 关了 CSRF,子 Controller 没重写,那子类也跟着失效;反之父类开了,子类想关某个 action,必须在 beforeAction 里干预,不能只设属性
CSRF token 过期或刷新不及时会导致批量失败
Yii 默认把 token 存在 session 里,session 过期或用户长时间未操作,token 就失效。但用户未必立刻退出登录,继续点提交就会卡在 400。
- 不要依赖「用户看到错误再刷新页面」——电商结算页这种关键路径,得在 JS 提交前先 fetch 一次
/site/csrf-token接口(自己写个轻量 action 返回新 token),再填进请求 - 避免在高并发场景下频繁调用
$request->getCsrfToken(),它每次都会重生成并更新 session,可能引发 session 锁竞争;可考虑缓存 token 到 Redis,设置短 TTL(比如 5 分钟),由前端定时刷新 - 移动端 WebView 或小程序嵌套 H5 时,Cookie 的 SameSite 属性可能阻断 token 传递,需确认 Nginx/Apache 是否设置了
SameSite=Lax或None; Secure,否则 iOS 14+ 和新版 Chrome 会丢掉 _csrf cookie
最常被忽略的是:CSRF 防护的有效性完全依赖 cookie 安全性。如果 cookieValidationKey 泄露、Cookie 缺少 HttpOnly 和 Secure 标志、或站点混用 HTTP/HTTPS,那前面所有配置都形同虚设。











