43

Is there a way to disable CSRF validation for some actions of the controller keeping it enabled for the other ones?

In my case I have several configurable Action classes, that are intended to be injected into controllers. I can't pass csrf validation token into the AJAX request because the thing I'm working with is external (made not by me) WYSIWYG plugin at the frontend. Yes, I can still disable csrf validation of the whole controller using these actions, but it may be insecure.

arogachev
  • 31,868
  • 6
  • 105
  • 113
coderlex
  • 542
  • 1
  • 4
  • 9

4 Answers4

93

For the specific controller / actions you can disable CSRF validation like so:

use Yii;

...

Yii::$app->controller->enableCsrfValidation = false;

Or inside a controller:

$this->enableCsrfValidation = false;

Take a look at $enableCsrfValidation property of yii\web\Controller.

Update:

Here is some specification.

If you want to disable CSRF validation for individual action(s) you need to do it in beforeAction event handler because CSRF token is checked before action runs (in beforeAction of yii\web\Controller).

/**
 * @inheritdoc
 */
public function beforeAction($action)
{            
    if ($action->id == 'my-method') {
        $this->enableCsrfValidation = false;
    }

    return parent::beforeAction($action);
}

Official docs:

arogachev
  • 31,868
  • 6
  • 105
  • 113
  • 2
    Checking of this parameter is processing in beforeAction, so it would be useless to do this inside of action. – yujin1st May 04 '15 at 05:05
  • @yujin1st I actually didn't mention anything about where exactly to place it, but yes, it's needed to be placed in `beforeAction`. Thanks for remark, updated the answer. – arogachev May 28 '15 at 09:28
  • but I had used your code exactly as you had it replacing with the action – Michael St Clair Jul 02 '15 at 17:53
  • The `$action` should already contain action id, try to `var_dump` it inside the method, what's the result? – arogachev Jul 02 '15 at 17:55
  • it gave me an array where the action id I was look for was `$action['id']`, but when I tried to use that it gave me some error saying I couldn't use `$action` as an array. – Michael St Clair Jul 02 '15 at 17:58
  • Please edit $action == 'my-method' on $action->id == 'my-method' – Alex Oct 13 '15 at 07:33
  • 1
    @Alex Thanks for remark, corrected the answer. By the way, you can suggest edit too. – arogachev Oct 13 '15 at 08:06
5

Put this inside your controller, just replace index with whatever action you want to disable csrf on.

public function beforeAction()
{      
    if ($this->action->id == 'index') {
        $this->enableCsrfValidation = false;
    }
    return true;
}
Reborn
  • 19,713
  • 8
  • 36
  • 61
Michael St Clair
  • 4,164
  • 5
  • 43
  • 67
  • why using long route `Yii::$app->controller->` when you are in the controller use `$this` for disabling for the current controller action.. – Reborn Feb 27 '18 at 23:28
5

For me this is what worked

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

i have tried this and it worked .

Go to the specific controller and write this at the top.

public $enableCsrfValidation = false;
Shuhad zaman
  • 2,298
  • 22
  • 25
  • This disables CSRF validation for ALL actions in the controller. OP asked about individual actions. – Sarke May 25 '21 at 08:03