KillMeAgain 2015-07-15 15:53:12 23613次浏览 6条回复 24 15 0

由于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 中关闭。

觉得很赞
  • 回复于 2015-07-17 17:51 举报

    beforeAction里面这样应该也是可以的吧?

    
    public function beforeAction($action)
    {
        $this->enableCsrfValidation = false;
        return parent::beforeActin($action);
    }  
    
    
    6 条回复
    回复于 2015-07-20 14:00 回复

    这样写是关闭了controller 里面验证

    回复于 2015-07-20 14:04 回复

    这是关闭了controller里所有action的验证了csrf验证了吧.
    而且要全部关闭的话也不用那么麻烦,直接在controller里覆盖掉父类的enableCsrfValidation

    回复于 2015-07-28 13:10 回复

    if(in_array($action, $this->actions)){
        $this->controller->enableCsrfValidation = false;
    }
    

    恩,我的意思是把 parent::beforeAction 放在设置 enableCsrfValidation 属性的后面,这里,你同样可以用 in_array 进行判断是否设置 enableCsrfValidation 不是么?

    回复于 2015-08-10 20:10 回复

    :请问一下,在yii 1中能用上面的方法?

    回复于 2015-10-19 14:29 回复

    好像不行

    回复于 2018-12-18 15:05 回复

    可以这样,不过代码要改一下

    public $enableCsrfValidation = true;
        public $noCsrfActions = ['add'];
    
        public function beforeAction($action)
        {
            if(in_array($action->id, $this->noCsrfActions)) {
                $this->enableCsrfValidation = false;
            }
            return parent::beforeAction($action);
        }
    
    

    这样用起来简洁,不过通过行为的方式,模式更好一些

  • 回复于 2015-07-17 22:51 举报

    好使!赞一个。

  • 回复于 2015-07-21 09:11 举报

    原来可以这样~,我以前都是直接在beforeaction里关闭

  • 回复于 2015-07-21 14:54 举报

    good 点赞

  • 回复于 2015-08-06 10:23 举报

    其实 本质都是借助beforeAction事件 做处理, 当然了 结合behavior 更简洁, 更易于复用, 更符合开闭原则什么的...不过也带来一点点点点可以忽略不计的效率问题

    觉得很赞
  • 回复于 2018-09-05 18:44 举报

    学习了,赞

您需要登录后才可以回复。登录 | 立即注册