Yii禁用CSRF保护机制的操作

14

我需要从不同的控制器和子域发送相同的表单数据,但在某些情况下需要禁用CSRF验证。

例如:

登录表单:

  • 位置1:主页example.com

  • 位置2:account.example.com/login

  • 位置3:gate.example.com

我需要只有在从位置1发送数据到位置2时才禁用验证。

我使用了$form = $this->beginWidget('CActiveForm',...

我该如何做?

我认为csrf cookie是不跨域的!


谢谢大家。这是不可能的。我必须拒绝这个想法。那不是我想表达的意思。在我的情况下,我必须检查引荐者。 - spy-enot
1
你也可以在 normalizeRequest 中检查 referer。 - user133408
8个回答

31

CSRF验证会在加载网页的早期进行,甚至在调用控制器之前。您想覆盖CHttpRequest类以告诉它忽略某些路由。

protected/components文件夹中创建一个名为HttpRequest.php的文件,并添加以下内容。



class HttpRequest extends CHttpRequest
{
    public $noCsrfValidationRoutes=array();

    protected function normalizeRequest()
    {
            //attach event handlers for CSRFin the parent
        parent::normalizeRequest();
            //remove the event handler CSRF if this is a route we want skipped
        if($this->enableCsrfValidation)
        {
            $url=Yii::app()->getUrlManager()->parseUrl($this);
            foreach($this->noCsrfValidationRoutes as $route)
            {
                if(strpos($url,$route)===0)
                    Yii::app()->detachEventHandler('onBeginRequest',array($this,'validateCsrfToken'));
            }
        }
    }
}

然后,在protected/config中编辑您的配置文件,并填入以下信息:

    // application components
'components'=>array(
    ....

    'request' => array(
        'enableCsrfValidation' => true,
        'class'=>'HttpRequest',
        'noCsrfValidationRoutes'=>array(
            'controllername/actionname',
        ),
    ),
 )

controllername/actionname 的示例是:'api2/getAssociated' - Igor Parra

8

如果要禁用CSRF,请将以下代码添加到您的控制器中:

public function beforeAction($action) {
    $this->enableCsrfValidation = false;
    return parent::beforeAction($action);
}

Yii 2系统,话题日期:没有Yii 2。 - Denis Chenu

4

顾名思义,它是“跨站点请求伪造(Cross-Site-Request-Forgery)”,因此它不是跨域的,也一定不能是跨域的 :)

CSRF已启用在请求组件中,所以只需获取请求组件并重新配置即可:

Yii::app()->request->enableCsrfValidation = false;

我不太确定应该把它放在哪里,可能是在行动的开始。


谢谢。我怀疑过了,我试图在所有地方找到这行代码,但是没有任何结果。 - spy-enot
尝试在控制器的 init 方法中设置 $_POST 的 csrf 值,这样可以正常运行。 - user133408
我注意到我已经定制了HTTP请求组件。在CHttpRequestnormalizeRequest方法中,将csrf验证附加到应用程序组件的onBeginRequest事件上。您可以子类化CHttpRequest并进行调整。 - user133408

3

2
要禁用csrf,请在main.php中添加以下内容。
return array(
'components'=>array(
    'request'=>array(
        'enableCsrfValidation'=>false,
    ),
),
);

1

要禁用CSRF,请在您的控制器中添加以下代码:

public function beforeAction($action)
{
    Yii::app()->request->enableCsrfValidation = false;
    return parent::beforeAction($action);
}

1
这里有另一种方法可以禁用特定操作。
public function beforeAction($action)
{
    Yii::$app->request->enableCsrfValidation = $action->id !== 'index'; //action name to disable CSRF for
    return parent::beforeAction($action);
}

0

我对Willem-Renzema的方法稍有不同。

<?php
class HttpRequest extends CHttpRequest
{
    public $noCsrfValidationRoutes=array();

    public function validateCsrfToken($event) { 
        $url=Yii::app()->getUrlManager()->parseUrl($this);
        foreach($this->noCsrfValidationRoutes as $route)
        {
            if(strpos($url,$route)===0)
                return true;
        }
        return parent::validateCsrfToken($event);
    }
}

配置与他的答案相同,但他的方法给了我错误,因为在normalizeRequest()函数中,使用$url=Yii::app()->getUrlManager()->parseUrl($this);并不总是能够获取到URL。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接