0

I'm trying to send data using ajax POST request but I'm always redirected to login page even if I authorize the method to anonymous users (['actions' => ['update', 'test'], 'allow' => true]). When I test with a GET request there is no problem.

My controller :

public function behaviors() {
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                ['actions' => ['update', 'test'], 'allow' => true],
            ],
        ],
    ];
}

public function actionTest() {
    Yii::$app->request->enableCsrfValidation = false;

    echo 'ok';
}

I use Postman to test requests

Reborn
  • 19,713
  • 8
  • 36
  • 61
  • 1
    Read [How to ask a question](https://stackoverflow.com/help/how-to-ask). So post your controller, model or something else. – Sfili_81 May 07 '18 at 08:56
  • 1
    Turning off CSRF validation inside the action method will not apply. You need to move it into `Controller::init()` or `Controller::beforeAction()`, optionally checking current action name. See also https://stackoverflow.com/questions/28526873/disable-csrf-validation-for-individual-actions-in-yii2. – lubosdz May 07 '18 at 11:02
  • @lubosdz turning off the CSRF make you open to RISKS related to Xss, this is not a solution – Reborn May 07 '18 at 16:59
  • Which base controller your controller extends from? – Paul May 08 '18 at 01:05
  • @MuhammadOmerAslam Actually I was not trying to find the solution via turning off CSRF validation. I just saw wrong place for the token. I guess the root of the problem might be in incorrectly building HTML form, which does not attach CSRF token properly. mlcsthor you might want to post here also how you build your sign-in form since it SHOULD be POSTed (don't use GET for sign in) and the form SHOULD also include CSRF token. Check out login example https://stackoverflow.com/questions/27304066/yii2-step-by-step-guide-on-login-from-table-in-mysql – lubosdz May 08 '18 at 19:26

3 Answers3

1

The solution you used is not a solution actually, its like if you cant open the lock with a key just remove the lock.

Mostly you get the 400 Bad Request if you are making an Ajax Post request without sending the CSRF parameters, I never faced the problem like being redirected to the login page.

But if your problem is resolved by disabling the CSRF Validation then you should follow this method while making any ajax requests.

In your config, you define the csrf parameter name using csrfParamin the request component like this

'request' => [
     'csrfParam' => '_csrf-app',
],

This can be different for you if it is already defined.

You have to send this param _csrf-app with the csrf value in the ajax request along with your post data. and for retrieving the value for the csrf you can use javascript yii.getCsrfToken() method, or Yii::$app->request->csrfToken if in view via php.

See this example call you can hardcode the name of the param _csrf-app or use Yii::$app->request->csrfParam if your script is inside the view file.

$.ajax({
    url:'/add',
    data:{'_csrf-app':yii.getCsrfToken()}
    success:function(data){}
});

Hope this solves your problem.

Reborn
  • 19,713
  • 8
  • 36
  • 61
0

lubosdz's suggestion solved the problem

Modified controller :

public function behaviors() {
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                ['actions' => ['update', 'test'], 'allow' => true],
            ],
        ],
    ];
}

public function beforeAction($action) {
    if ($action->id == 'test') {
        $this->enableCsrfValidation = false;
    }

    return parent::beforeAction($action);
}

public function actionTest() {
    echo 'ok';
}
  • why would you leave yourself open to Xss by using this solution, never turn off the `csrfValidation`. do you `400 Bad Request` error ? – Reborn May 07 '18 at 17:01
  • Solving the issue via turning off CSRF validation is not encouraged solution. Seems like the CSRF token is not validated properly. Please show the code how you build HTML login formular + LoginModel with validation rules. – lubosdz May 08 '18 at 19:29
0

I found a solution that looks a bit like yours Muhammad Omer Aslam : by serializing the form in JavaScript I can send directly all the fields and the csrf token generated by the ActiveForm.

$.ajax({
    url: ...,
    type: 'POST',
    data: $('#myForm').serialize(),
    success: (response) => { ... }
})
  • you had written that you were sending ajax call but i didn't had a clue that you are submitting form, i thought it was like a custom action in controller for like we use select2 to populate the drop-down, otherwise if its a form the hidden input for csrf-token is already injected and can be grabbed using `form.serialize()` otherwise, if its a custom ajax you can always use the method i specified and you will never run into a problem. – Reborn May 10 '18 at 23:17