我需要从不同的控制器和子域发送相同的表单数据,但在某些情况下需要禁用CSRF验证。
例如:
登录表单:
位置1:主页example.com
位置2:account.example.com/login
位置3:
gate.example.com
我需要只有在从位置1发送数据到位置2时才禁用验证。
我使用了$form = $this->beginWidget('CActiveForm',...
我该如何做?
我认为csrf cookie是不跨域的!
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如果要禁用CSRF,请将以下代码添加到您的控制器中:
public function beforeAction($action) {
$this->enableCsrfValidation = false;
return parent::beforeAction($action);
}
顾名思义,它是“跨站点请求伪造(Cross-Site-Request-Forgery)”,因此它不是跨域的,也一定不能是跨域的 :)
CSRF已启用在请求组件中,所以只需获取请求组件并重新配置即可:
Yii::app()->request->enableCsrfValidation = false;
我不太确定应该把它放在哪里,可能是在行动的开始。
init
方法中设置 $_POST
的 csrf 值,这样可以正常运行。 - user133408CHttpRequest
的normalizeRequest
方法中,将csrf验证附加到应用程序组件的onBeginRequest
事件上。您可以子类化CHttpRequest
并进行调整。 - user133408从控制器禁用你的 CSRF:
class MyController extends Controller
{
public $enableCsrfValidation = false;
return array(
'components'=>array(
'request'=>array(
'enableCsrfValidation'=>false,
),
),
);
要禁用CSRF,请在您的控制器中添加以下代码:
public function beforeAction($action)
{
Yii::app()->request->enableCsrfValidation = false;
return parent::beforeAction($action);
}
public function beforeAction($action)
{
Yii::$app->request->enableCsrfValidation = $action->id !== 'index'; //action name to disable CSRF for
return parent::beforeAction($action);
}
我对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。
normalizeRequest
中检查 referer。 - user133408