使用yii2框架发送post请求报错400错误,关闭(开启)csrf的验证解决方案

本文介绍了在Yii2框架中遇到POST请求返回400错误的原因,主要是由于默认开启的CSRF验证。文章详细讲解了如何全局开启或关闭CSRF验证,以及如何在特定控制器或action中禁用和启用此验证。对于需要关闭CSRF验证的场景,如API接口对接,提供了相应的配置和代码示例。

400错误原因

出现这个错误的原因是因为yii框架默认是开启了csrf验证
yii2的csrf的实现功能是在yii\web\request类实现功能的。
request类中的属性,默认是true的。

public $enableCsrfValidation = true;

所以我们在配置文件中的request组件中可以配置该值

request => [
'enableCookieValidation' => true,
]

想要详细了解你看request组件的csrf

全局使用csrf验证

我们直接在配置文件中设置enableCookieValidation为true

request => [ 
  'enableCookieValidation' => true, 
]
如果不需要使用csrf的话,设置'enableCookieValidation' => false,
但是这是不安全的,因此yii2的yii\web\request中的enableCookieValidation默认设置为true的,
也就是默认开启csrf的,所以我们也可以不配置这个值,默认开启。

如果开启csrf,因为这是全局的,所以在任何的post请求都会要求认证,所以我们在post数据的时候,就必须设置csrf的数据隐藏在表单中。

<input type="hidden" name="_csrf" id='csrf' value="<?= Yii::$app->request->csrfToken ?>"> 

post数据的时候必须要把这个值post过去,这个值的产生

<?= Yii::$app->request->csrfToken ?>,返回一个加密后的csrfToken。

所以无论是post表单还是ajax的post过去,都必须设置csrfToken这个值,并且要提交时要post过去。如果没有的话,就会发生错误,无法认证通过。

如果想在某些控制器不想使用csrf验证的话

方法很简单,直接设置

public function init(){
    $this->enableCsrfValidation = false;
}
或者
public $enableCsrfValidation = false;

因为这个Controller继承与yii\web\Controller ,将相当于继承于enableCsrfValidation这个属性,那么在创建控制器实例时,就会在这个控制器关闭csrf功能,访问这个控制器的post的方式时,也就不会进行验证。

举一个例子,比如我们开发API的时候,微信那边的接口需要post数据给我们的接口时,由于微信端不知道csrfToken,所以访问post数据的时候,如果开启全局csrf的话,那肯定不能访问成功的。所以这时就需要关闭这个API 的csrf。

如果要具体关闭至某一个action

有时在一些功能中,我们需要在某一个action中关闭csrf验证。
我们知道对于csrf的验证是在beforeAction($Action)中实现的,
下面我们可以在Controller中重写beforeAction($action)这个方法
public function beforeAction($action) {
 
	$currentaction = $action->id;
 
	$novalidactions = ['dologin'];
 
	if(in_array($currentaction,$novalidactions)) {
 
    	$action->controller->enableCsrfValidation = false;
    }
	parent::beforeAction($action);
 
	return true;
}



传入的参数$action是controller针对这个访问实例化的对象,里面包含很多信息,大家可以打印看看。
首先执行$action->id获取当前的访问的action名称。
而$novalidactions是一个数组,里面是action名称,
这些action都是是你需要关闭csrf的认证的操作(需要关闭csrf认证的操作)。

通过当前的访问的action是否在这个$novalidactions中,
如果在,说明这个action需要关闭csrf功能,所以就将这个控制器实例的设置为
$action->controller->enableCsrfValidation = false
接下来再执行parent::beforeAction($action),
此时传入来的$action里的controller实例的enableCsrfValidation已变为false。
最后一定要返回true,否则的话,不会往下执行action操作的。

如果局部开启csrf验证

首先在配置文件要设置 全局不使用csrf

request => [
'enableCookieValidation' => false,
]

要在控制器中开启,只需要设置

public $enableCsrfValidation = true

则整个控制器都会开启

要在action中开启

public function beforeAction($action) {
$currentaction = $action->id;
$accessactions = ['dologin'];
i f(in_array($currentaction,$accessactions)) {
       $action->controller->enableCsrfValidation = true;
 }
 
    parent::beforeAction($action);
    return true;
}

$accessactions是需要开启csrf的action的名称,
将设置$action->controller->enableCsrfValidation = true,当前操作可以开启csrf。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值