【问题标题】:Getting bad request (#400) on Ajax calls using Yii 2使用 Yii 2 在 Ajax 调用上收到错误请求 (#400)
【发布时间】:2019-11-25 00:35:10
【问题描述】:

这是我的代码:

$(document).on('change', '#tblhotel-int_zone_id', function(e){
    var zoneId = $(this).val();
    var form_data = {
        zone: zoneId
    };
    $.ajax({
        url: "state",
        type: "POST",
        data: form_data,
        success: function(response)
        {
            alert(response);
        }
    });
});

这表明:

错误请求 (#400):无法验证您的数据提交。

我已经有了<?= Html::csrfMetaTags() ?>。我该如何解决这个问题?

【问题讨论】:

    标签: jquery ajax yii2


    【解决方案1】:

    注意:请参阅 the answer from Skullcrasher 以正确方式解决问题,因为我的回答建议禁用 Cross-Site Request Forgery


    您的 enableCsrfValidation 有问题。要了解更多信息,您可以阅读here

    要禁用 CSRF,请将此代码添加到您的控制器:

    public function beforeAction($action) {
        $this->enableCsrfValidation = false;
        return parent::beforeAction($action);
    }
    

    这将禁用所有操作。您可能应该根据 $action 仅对特定操作禁用它。

    【讨论】:

    • 在这种情况下(当没有条件影响禁用结果时)没有必要将其放入 beforeAction 中。您可以将其重新定义到您的控制器中,例如: public $enableCsrfValidation = false;但是在 beforeAction 中,您可以指定禁用验证的具体操作
    • 正确,如果您想为特定操作禁用它,这很容易。
    • 不要这样做!它正在禁用 CSRF 保护!
    • 为什么这被标记为正确答案?它不是。这不是一个解决方案。这就像因为钥匙坏了,就把你家的门拆了。
    • 因此请注意以查看更好的答案,我不能删除 ckeckmark 只有 OP 可以这样做。顺便说一句,拆除门是进入房子的有效方式,它可能不是最好的方式,但它是一种方式。
    【解决方案2】:

    正如 Mihai P. 的回答所说,您的问题是 CSRF 验证。您也可以禁用对操作的验证,但这不是一个好的解决方案。

    由于您的 Ajax 请求的验证存在问题,您还可以使用 Yii JavaScript 函数将 CSRF 令牌添加到您在 Ajax 请求中发送的表单数据中。

    只需尝试将令牌添加到您的表单数据中,如下所示:

    var form_data = {
        zone: zoneId,
        _csrf: yii.getCsrfToken()
    };
    

    我希望这会有所帮助,因此您不必禁用 CSRF 验证。

    除了手动添加 CSRF 令牌,您还可以检查请求中是否设置了 X-CSRF 标头。

    【讨论】:

    • 这是更好的答案,不是我的。
    • 我在 Vue.js(Index.vue 文件)中尝试这个,但它不起作用,嗯,不断收到“Bad request cannot validate your data”(400)错误...跨度>
    【解决方案3】:

    在布局底部添加此代码:

    <script>
        $.ajaxSetup({
            data: <?= \yii\helpers\Json::encode([
                \yii::$app->request->csrfParam => \yii::$app->request->csrfToken,
            ]) ?>
        });
    </script>
    

    【讨论】:

      【解决方案4】:

      用途:

      var csrfToken = $('meta[name="csrf-token"]').attr("content");
      $.ajax({
          url: 'request',
          type: 'post',
          dataType: 'json',
          data: {param1: param1, _csrf : csrfToken},
      });
      

      更多详情:Yii2: Using csrf token

      【讨论】:

        【解决方案5】:

        您需要在 before action 函数中禁用 CSRF 验证:

        public function beforeAction($action) {
            if($action->id == "action name need to disable")
                $this->enableCsrfValidation = false;
            return parent::beforeAction($action);
        }
        

        或者使用GET method

        【讨论】:

        • 这是无效的,因为它增加了遭受 csrf 攻击的风险。
        【解决方案6】:

        这行得通。用你自己的改变 csrfParam 在 Config/main.php 中

        'components' => [
            'request'=>[
                'csrfParam'=>"othername"
            ],
            ...
        

        请记住,您必须在请求中包含与您在配置中定义的名称相同的令牌。

        【讨论】:

          【解决方案7】:

          虽然这是一篇有很多答案的旧帖子,但发布的所有答案都缺少一些东西,所有这些都解决了正确的问题,但是当调用 ajax POST 请求以及您的数据时,您应该使用 @987654322提供@函数

          • yii.getCsrfParam()获取token的参数名称
          • yii.getCsrfToken()获取csrf-token的token或实际值

          好像您在request 组件配置下的config.phpweb.php 内定义了不同的前端参数名称

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

          那么您需要动态获取该名称,上面的函数可以帮助您。

          你应该

          var form_data = {
              zone: zoneId
          };
          form_data[yii.getCsrfParam()]=yii.getCsrfToken();
          

          【讨论】:

            【解决方案8】:

            /backend/config/main-local.php

            'components' => [
                'request' => [
                    'cookieValidationKey' => 'unique code',
                    'csrfCookie' => ['httpOnly' => true, 'path' => '/admin/'],
                ],
            ],
            

            /frontend/config/main-local.php

            'components' => [
                'request' => [
                    'cookieValidationKey' => 'unique code',
                    'csrfCookie' => ['httpOnly' => true, 'path' => '/'],
                ],
            ],
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-10-20
              • 2013-08-03
              • 1970-01-01
              • 2015-06-12
              • 1970-01-01
              • 1970-01-01
              • 2019-10-26
              相关资源
              最近更新 更多