Li Ming

Yii2 在某一 action 中关闭 CSRF 校验

Yii2 默认是开启了 CSRF 校验的,今天需要做一个接口给手机 app 调用,用于错误报告记录,没关闭 CSRF 校验的情况下,提示 400 Bad Request。

那么如何关闭 CSRF 校验呢?

全局关闭

全局关闭有两种方式:

  • 全站关闭,在 config/web.php 中添加如下代码:
    'request' => [
      'enableCsrfValidation' => false,
    ],
  • 整个 Controller 关闭,在当前 Controller 中添加如下代码:
    public $enableCsrfValidation = false;

以上两种方法,都是大面积的关闭,如果需要控制到更精确,且往下继续阅读。

方法一:通过 Behavior 控制

由于 Yii2 Controller Csrf 验证是在 beforeAction 中完成的,所以在 action 中指定 $this->enableCsrfValidation = false;
不能实现局部关闭 Csrf。

新建一个 Behavior

  • 在根目录下创建一个 behaviors 文件夹,和 config、models 同级
  • 在 behaviors 中新建文件 NoCsrf.php,代码如下:
    <?php

namespace app\behaviors;

use Yii;
use yii\base\ActionEvent;
use yii\base\Behavior;
use yii\web\Controller;

class NoCsrf extends Behavior
{
public $actions = [];
public $controller;
public function events()
{
return [Controller::EVENT_BEFORE_ACTION => ‘beforeAction’];
}
public function beforeAction($event)
{
$action = $event->action->id;
if(in_array($action, $this->actions)){
$this->controller->enableCsrfValidation = false;
}
}
}

在 Controller 中添加 Behavior

 [
            'class' => NoCsrf::className(),
            'controller' => $this,
            'actions' => [
                'action-name'
            ]
        ]
    ];
}

这样就实现了在 action 中关闭 Csrf 而不是在整个 Controller 中关闭。

方法二:实现 Controller 自身的 beforeAction 方法

/*
     * 局部关闭 CSRF 校验
     */
    /*public function beforeAction($action) {  
        $currentaction = $action->id;  
        $novalidactions = ['error-report'];  
        if(in_array($currentaction,$novalidactions)) {  
            $action->controller->enableCsrfValidation = false;  
        }  
        parent::beforeAction($action);
        return true;  
    }*/

参考资料