0

I was trying to implement page caching in Yii2 advanced project and everything seemed to be super cool. And suddenly I was hit by a strange issue.

Case: On the homepage of the website there is some dynamic data like showing records from DB, info of current user like the name (if the user is logged-in) and some static content. Also, a search input field which fetches result using AJAX call.

To speed page loading I implemented PageCaching provided by Yii2. And all worked good. But one issue I got stuck at is that after user log-in the ajax call didn't work and gave Error:

Bad Request (#400): Unable to verify your data submission.

I get this error till cache is refreshed after the set duration or I disable cache.

Is this issue related to cookie/session or something else? How to resolve it?

Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68

1 Answers1

0

The 400 Bad Request is because the csrf-token is not being sent, with the request which is required to prevent cross-site attacks by Yii whenever you use POST to submit a page or ajax request, if you create an ActiveForm then it creates an input automatically with the token value.

You didn't add the code that you are using for the ajax call so not clear if you are using it for only one field or the whole form, so I would suggest the concerning part only.

You need to send the csrf-token and you can get it via javascript using yii.js and calling these 2 methods

  • yii.getCsrfParam() to get the parameter name of the token
  • yii.getCsrfToken() to get the token or actual value of the csrf-token

The csrfParam name is configured inside your frontend/config.php or config/web.php depending on the app you are using (advance /basic) under the request component like below

'components'=>[
    ......
    ......
    'request' => [
        'csrfParam' => '_csrf-frontend',
    ],
    ......
    ......
]

So what you need to do is either change the request method from POST to GET and send data via query string or use the following way to send the POST request.

Note: You should change the URL and add the csrf data into your existing data that you are sending with the request

let data={};
data[yii.getCsrfParam()]=yii.getCsrfToken();
$.ajax(
    {
        method:"POST",
        url:"/site/test",
        data:data,
        success:function(data) {
            console.log(data);
        },
        error:function(jqXHR,textStatus,errorThrown) {
            console.log(jqXHR,textStatus,errorThrown);
        }
    }
);

If you have a test action inside the SiteController with the following code, then the above ajax call should show you the $_POST array inside the console with the csrf param and token value as key=>value.

public function actionTest()
{
    print_r($_POST);
}
Muhammad Omer Aslam
  • 22,976
  • 9
  • 42
  • 68
  • Thanks for the reply. – Sameer Sood Dec 13 '18 at 09:27
  • Thanks for the reply. But still the issue was not resolved. I think you have missed the "PageCache" here. Let me explain: I am using page cache on homepage, which has signup form and search input field (which uses ajax POST call to fetch data). When user login page is reloaded (mind here still page cache is being used) and then tries to search then ajax call used by search input field show the above error. I am also using the same code which you have written in reply. I am sending the csrf token. Is it really issue related to csrf or page caching in yii2? – Sameer Sood Dec 13 '18 at 09:33
  • well as far as i have experienced 404 on ajax POST call mostly relates with csrf token missing, can you please update your question and add the relevant code @SameerSood also try disabling the csrf by using `$this->enableCsrfValidation=false` within the `beforeAction` as in this [POST](https://stackoverflow.com/questions/28526873/disable-csrf-validation-for-individual-actions-in-yii2) and check if the ajax call works, if it does then it is definately relates. – Muhammad Omer Aslam Dec 14 '18 at 22:22
  • Yes I had already tried with disabling csrf in my controller and then every thing works. But i am not satisfied with this solution. And I want to know the reason behind this issue. Which code section shall I provide so that we can verify the real issue – Sameer Sood Dec 15 '18 at 05:28
  • @SameerSood if it works after diaabling csrf then it is what i am saying and the code is provided above you should add your code now or i wont be able to help any further as i have already suggested a solution – Muhammad Omer Aslam Dec 15 '18 at 11:46
  • @SameerSood add the code for the ajax call and the action to which you are sending the call also which template you are using `advance` or `basic` ? – Muhammad Omer Aslam Dec 16 '18 at 10:35