Yii2 默认开启CSRF防护,仅对POST、PUT、DELETE等非安全方法生效,依赖_csrf字段或X-CSRF-Token请求头;手动传Token应使用getCsrfToken()输出并统一设请求头;SameSite需在PHP层设为Lax以兼顾安全与可用。

Yii2 默认 CSRF 防护是否开启?
默认开启,但只对 POST、PUT、DELETE 等非安全方法生效,且依赖 csrfParam 对应的隐藏字段或请求头。如果你没改过 Request 或 Form 配置,_csrf 字段已自动注入表单,后端也默认校验——但前提是请求走的是 Yii2 的标准表单提交或 yii\web\JsExpression 包装的 AJAX。
CSRF Token 怎么手动传给前端 JS?
别从 DOM 里反复 querySelector 抓 _csrf 值,容易漏或错位。正确做法是用 Yii2 提供的 Yii::$app->request->getCsrfToken() 在视图中直接输出:
const CSRF_TOKEN = "<?= Yii::$app->request->getCsrfToken() ?>";
然后在 AJAX 请求头里统一加:
headers: { 'X-CSRF-Token': CSRF_TOKEN }
常见错误现象:400 Bad Request + Missing required parameter: _csrf,基本是因为 JS 请求没带 token,或带了但后端没配好验证逻辑。
SameSite 属性怎么配才不破坏登录和跳转?
Yii2 不直接控制 Cookie 的 SameSite,得靠 PHP 或 Web 服务器层设置。PHP 7.3+ 推荐在入口 web/index.php 顶部加:
ini_set('session.cookie_samesite', 'Lax');
注意三点:
-
Lax是平衡安全与可用的底线,Strict会导致从外部链接进站时 session 丢失 - 如果用了
yii\web\Session自定义配置,得同步在cookieParams里显式设'sameSite' => 'Lax' - Nginx/Apache 也可用
add_header或Header edit改响应头,但优先走 PHP 层,避免覆盖 Yii 的其他 cookie 设置
AJAX 提交表单时 CSRF 校验失败的典型原因
不是 token 过期,而是请求方式和后端预期不匹配。Yii2 默认只从以下位置读 token:
- POST 表单字段:
_csrf - HTTP 头:
X-CSRF-Token - GET 查询参数(仅限调试,生产禁用)
容易踩的坑:
- 用
fetch发POST但 body 是JSON,没把_csrf放进 body 或 header —— 此时必须手动加X-CSRF-Token头 - 表单用了
enctype="multipart/form-data",但 JS 拦截后没把_csrf字段 append 进FormData - 前端框架(如 Vue)绑定表单时,没把
_csrf当作 reactive 字段,导致提交时值为空
CSRF 和 SameSite 是两层防御:前者防伪造请求内容,后者限制 Cookie 发送场景。漏掉任意一层,都可能让攻击者绕过验证。特别是当你的应用有 iframe 嵌入、第三方 OAuth 回调或跨子域跳转时,SameSite 的取值和 csrfParam 的传输路径,得一个个对齐实际流量走向。










