yii 2 局部關閉 CSRF 攔截


最近在拿 yii 2.0 開發ajax提交,在 post 請求接口時,提示數據無法驗證,於是查詢 yii 錯誤日志,發現錯誤為

exception ‘yiiwebBadRequestHttpException’ with message ‘Unable to verify your data submission

於是查看源代碼,yii 2.0 在 我們繼承的頂級 controller 中,有下列屬性

/**
 * @var boolean whether to enable CSRF validation for the actions in this controller.
 * CSRF validation is enabled only when both this property and [[Request::enableCsrfValidation]] are true.
*/
 public $enableCsrfValidation = true;

106 行的 beforeAction 內,對他做了處理

``` public function beforeAction($action) { if (parent::beforeAction($action)) { if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) { throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.')); } return true; } else { return false; } }

```

於是找到錯誤原因:

yii 2.0 內,對 CSRF 攻擊做了處理,會對 post 提交的數據做 token 驗證,而微信 post 到我們服務器的代碼中,沒有帶上這個 token ,所以會驗證失敗

解決方法:

1、在我們的控制器里面,加上這行屬性,設置為 false

public $enableCsrfValidation = false;

你還可以直接修改頂層控制器的 $enableCsrfValidation ,但是不推薦這樣做!

 

2、關於如何在單獨的action中關閉Csrf驗證

由於Yii2 Controller Csrf驗證是在beforeAction中完成的,所以在action中指定
$this->enableCsrfValidation = false;
不能實現局部關閉Csrf。

如何實現

新建一個Behavior

<?php
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

?php

    public function behaviors()
    {
        return [
            'csrf' => [
                'class' => NoCsrf::className(),
                'controller' => $this,
                'actions' => [
                    'action-name'
                ]
            ]
        ];
    }

這樣就實現了在action中關閉Csrf而不是在整個Controller中關閉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM