【问题标题】:Laravel csrf token mismatch for ajax POST Requestajax POST请求的Laravel csrf令牌不匹配
【发布时间】:2015-12-20 17:21:39
【问题描述】:

我正在尝试通过 ajax 从数据库中删除数据。

HTML:

@foreach($a as $lis)
  //some code
  <a href="#" class="delteadd" id="{{$lis['id']}}">Delete</a>
  //click action perform on this link                  
@endforeach

我的 ajax 代码:

$('body').on('click', '.delteadd', function (e) {
e.preventDefault();
//alert('am i here');
if (confirm('Are you sure you want to Delete Ad ?')) {
    var id = $(this).attr('id');
    $.ajax({
        method: "POST",
        url: "{{url()}}/delteadd",
        }).done(function( msg ) {
        if(msg.error == 0){
            //$('.sucess-status-update').html(msg.message);
            alert(msg.message);
        }else{
            alert(msg.message);
            //$('.error-favourite-message').html(msg.message);
        }
    });
} else {
    return false;
}
});

这是我从数据库中获取数据的查询...

$a = Test::with('hitsCount')->where('userid', $id)->get()->toArray();

但是当我点击删除链接数据未删除并显示 csrf_token 不匹配时...

【问题讨论】:

标签: php jquery ajax laravel


【解决方案1】:

解决“X-CSRF-TOKEN”这个问题的最好方法是在你的主布局中添加以下代码,并继续正常进行你的ajax调用:

在标题中

<meta name="csrf-token" content="{{ csrf_token() }}" />

在脚本中

<script type="text/javascript">
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>

【讨论】:

  • 这是更好的解决方案,因为您可以在 .js 文件中使用它
  • 如果“global:false”怎么办?
  • 每次调用后如何更新csrf?第一次调用效果很好,由于 CSRF 令牌,后续调用失败。
  • @zarpio 我正在使用相同的方法。但是,在我的 ajax 调用中出现了令牌不匹配错误。请帮助我。
【解决方案2】:

您必须在您的 ajax 请求中添加 数据。我希望它会起作用。

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }

【讨论】:

  • 如果ajax函数位于.js文件中怎么办?
  • 它不适用于 Laravel 5.7。 zarpio 的回答是正确的。
  • @Brane 将令牌作为参数发送到函数中
  • 这在 Laravel 5.8 中不起作用。它仍然说令牌不匹配。在下面查看我的答案以获得简单的解决方案
  • 在 json 请求后 laravel 会更改 csrf 令牌吗?您需要将新的发送到主页吗?
【解决方案3】:

我刚刚在 ajax 调用中添加了headers:

  headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},

在视图中:

<div id = 'msg'>
     This message will be replaced using Ajax. Click the button to replace the message.
</div>

{{ Form::submit('Change', array('id' => 'ajax')) }}

ajax 函数:

<script>
 $(document).ready(function() {
    $(document).on('click', '#ajax', function () {
      $.ajax({
         type:'POST',
         url:'/ajax',
         headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
         success:function(data){
            $("#msg").html(data.msg);
         }
      });
    });
});
</script>

在控制器中:

public function call(){
    $msg = "This is a simple message.";
    return response()->json(array('msg'=> $msg), 200);
}

在 routes.php 中

Route::post('ajax', 'AjaxController@call');

【讨论】:

  • 是的,我猜这是正确的解决方案 $.ajaxSetup() 为每个请求进行全局配置
【解决方案4】:

我觉得最好把token放到form里面,通过id获取这个token

<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}">

还有 JQUery:

var data = {
        "_token": $('#token').val()
    };

这样,你的 JS 就不需要在你的刀片文件中了。

【讨论】:

    【解决方案5】:

    如果您使用的是模板文件,则可以将 meta 标签放在包含 meta 标签的头部 section(或任何名称)中。

    @section('head')
    <meta name="csrf_token" content="{{ csrf_token() }}" />
    @endsection
    

    接下来,您需要将headers 属性放入您的ajax(在我的示例中,我使用datatable 进行服务器端处理:

    "headers": {'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')}
    

    这是完整的 datatable ajax 示例:

    $('#datatable_users').DataTable({
            "responsive": true,
            "serverSide": true,
            "processing": true,
            "paging": true,
            "searching": { "regex": true },
            "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
            "pageLength": 10,
            "ajax": {
                "type": "POST",
                "headers": {'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')},
                "url": "/getUsers",
                "dataType": "json",
                "contentType": 'application/json; charset=utf-8',
                "data": function (data) {
                    console.log(data);
                },
                "complete": function(response) {
                    console.log(response);
               }
            }
        });
    

    完成此操作后,您应该为您的ajax 请求获得200 status

    【讨论】:

      【解决方案6】:

      知道有一个 X-XSRF-TOKEN cookie 是为了方便而设置的。 Angular等框架默认设置它。在文档https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token 中检查此内容 您可能喜欢使用它。

      最好的方法是使用元,以防 cookie 被停用。

          var xsrfToken = decodeURIComponent(readCookie('XSRF-TOKEN'));
          if (xsrfToken) {
              $.ajaxSetup({
                  headers: {
                      'X-XSRF-TOKEN': xsrfToken
                  }
              });
          } else console.error('....');
      

      这里推荐的元方式(你可以用任何方式放置字段,但元很安静):

      $.ajaxSetup({
          headers: {
              'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
          }
      });   
      

      注意decodeURIComponent()的使用,它是从用于存储cookie的uri格式解码的。 [否则你会在 laravel 中得到一个无效的 payload 异常]。

      这里是文档中有关 csrf cookie 的部分以进行检查: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

      这里还有 laravel (bootstrap.js) 默认如何为 axios 设置它:

      let token = document.head.querySelector('meta[name="csrf-token"]');
      
      if (token) {
          window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
      } else {
          console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
      } 
      

      你可以去查看resources/js/bootstrap.js

      这里读取cookie函数:

         function readCookie(name) {
              var nameEQ = name + "=";
              var ca = document.cookie.split(';');
              for (var i = 0; i < ca.length; i++) {
                  var c = ca[i];
                  while (c.charAt(0) == ' ') c = c.substring(1, c.length);
                  if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
             }
              return null;
          }
      

      【讨论】:

        【解决方案7】:

        id 添加到保存令牌的meta 元素

        <meta name="csrf-token" id="csrf-token" content="{{ csrf_token() }}">
        

        然后你可以在你的 Javascript 中得到它

        $.ajax({
          url : "your_url",
          method:"post",
          data : {
            "_token": $('#csrf-token')[0].content  //pass the CSRF_TOKEN()
          },  
          ...
        });
        

        编辑:更简单的方法,无需更改 meta 行。

        data : { 
            _token: "{{ csrf_token() }}" 
        }
        

        或者

        data : { 
            _token: @json(csrf_token()), 
        }
        

        感谢@martin-hartmann

        【讨论】:

        • 如果不想添加 id,只需使用:$("[name=csrf-token]").attr("content")。它将通过 name 属性获取正确的元素。
        • 也可以只在数据字段中做广告: data : { "_token": "{{ csrf_token() }}" //传递 CSRF_TOKEN() },
        【解决方案8】:

        如果您使用 jQuery 发送 AJAX 帖子,请将此代码添加到所有视图:

        $( document ).on( 'ajaxSend', addLaravelCSRF );
        
        function addLaravelCSRF( event, jqxhr, settings ) {
            jqxhr.setRequestHeader( 'X-XSRF-TOKEN', getCookie( 'XSRF-TOKEN' ) );
        }
        
        function getCookie(name) {
            function escape(s) { return s.replace(/([.*+?\^${}()|\[\]\/\\])/g, '\\$1'); };
            var match = document.cookie.match(RegExp('(?:^|;\\s*)' + escape(name) + '=([^;]*)'));
            return match ? match[1] : null;
        }
        

        Laravel 为所有请求添加一个 XSRF cookie,我们会在提交之前自动将其附加到所有 AJAX 请求中。

        如果有另一个函数或 jQuery 插件来做同样的事情,你可以替换 getCookie 函数。

        【讨论】:

          【解决方案9】:

          你必须在主文件中包含这一行

          &lt;meta name="csrf-token" content="{{ csrf_token() }}" /&gt;

          在调用 ajax 时,您必须实现 csrf 令牌,

          $.ajax({
          url:url,
          data:{
           _token:"{{ csrf_token() }}"
          },
          success:function(result){
           //success message after the controller is done..
          }
          })
          

          【讨论】:

            【解决方案10】:

            谁对@Deepak saini 接受的答案有问题,请尝试删除

            cache:false,
            processData:false,
            contentType:false,
            

            用于 ajax 调用。

            使用

            dataType:"json",
            

            【讨论】:

              【解决方案11】:

              如果您的会话过期,您可以使用它重新登录

              $(document).ajaxComplete(function(e, xhr, opt){
                if(xhr.status===419){
                  if(xhr.responseJSON && xhr.responseJSON.message=='CSRF token mismatch.') window.location.reload();
                }
              });
              

              【讨论】:

                【解决方案12】:

                如果您正在使用 laravel 7.0 项目并遇到此错误

                添加令牌作为要发送到控制器的参数的一部分将解决问题,就像上面给出的答案一样。这是 Laravel 保护您的站点免受跨站点攻击的结果。这要求您在每次提交表单时生成一个唯一令牌。

                "_token": "{{ csrf_token() }}"
                

                你现在可以拥有了;

                      const postFormData = {
                            'name'     : $('input[name=name]').val(),
                            "_token": "{{ csrf_token() }}"
                        }; 
                         
                      $.ajax({
                          url: 'pooling'
                          , type: 'post'
                          , data: postFormData
                          , dataType: 'json'
                          , success: function(response) { consolel.log(response) }
                        });
                

                【讨论】:

                  【解决方案13】:

                  对于 Laravel 5.8,如果您使用 ajax 提交的表单已经包含 _token 由Laravel 刀片模板引擎。

                  您必须将表单中已经生成的 csrf 令牌包含在您的 ajax 请求中,因为服务器会期待它,而不是元标记中的那个。

                  例如,Blade 生成的_token 输入字段如下所示:

                  <form>
                      <input name="_token" type="hidden" value="cf54ty6y7yuuyyygytfggfd56667DfrSH8i">
                      <input name="my_data" type="text" value="">
                      <!-- other input fields -->
                  </form>
                  

                  然后您使用 ajax 提交表单,如下所示:

                  <script> 
                      $(document).ready(function() { 
                          let token = $('form').find('input[name="_token"]').val();
                          let myData = $('form').find('input[name="my_data"]').val();
                          $('form').submit(function() { 
                              $.ajax({ 
                                  type:'POST', 
                                  url:'/ajax', 
                                  data: {_token: token, my_data: myData}
                                  // headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}, // unnecessary 
                                  // other ajax settings
                              }); 
                              return false;
                          }); 
                      }); 
                  </script>
                  

                  元标头中的 csrf 标记仅在您提交没有 Blade 生成的 _token 输入字段的表单时有用。

                  【讨论】:

                    【解决方案14】:

                    您应该在表单中包含一个隐藏的 CSRF(跨站请求伪造)令牌字段,以便 CSRF protection 中间件可以验证请求。

                    Laravel 自动为应用程序管理的每个活动用户会话生成一个 CSRF“令牌”。此令牌用于验证经过身份验证的用户是实际向应用程序发出请求的用户。

                    所以在进行 ajax 请求时,需要通过 data 参数传递 csrf 令牌

                    这是示例代码。

                    var request = $.ajax({
                        url : "http://localhost/some/action",
                        method:"post",
                        data : {"_token":"{{ csrf_token() }}"}  //pass the CSRF_TOKEN()
                      });
                    

                    【讨论】:

                      【解决方案15】:

                      Laravel 5.8
                      在ajax url中使用csrf(单独的js文件)

                      $.ajax({
                          url: "/addCart" + "?_token=" + productCSRF,
                          type: "POST",
                          ..
                      })
                      

                      【讨论】:

                        【解决方案16】:

                        在新的 laravel 中,您只需要在任何地方执行此操作即可。在 JS 或刀片文件中,您将拥有 csrf 令牌。

                        var csrf = document.querySelector('meta[name="csrf-token"]').content;
                        

                        它是普通的 JS。对于 Ajax,您需要这样做。

                        var csrf = document.querySelector('meta[name="csrf-token"]').content;
                            $.ajax({
                                url: 'my-own-url',
                                type: "POST",
                                data: { 'value': value, '_token': csrf },
                                success: function (response) {
                                    console.log(response);
                                }
                            });
                        

                        【讨论】:

                          【解决方案17】:

                          简单地将 csrfmiddlewaretoken: '{{ csrf_token }}' 放入数据中效果很好!!

                          $.ajax({
                              url : "url where you want to send data"
                              type : "POST", // http method
                              data : {
                                name:"...",
                                csrfmiddlewaretoken: '{{ csrf_token }}' , #this works for me
                              },
                          
                              // handle a successful response
                              success : function(data){
                                alert('......');
                              },
                              error : function() {
                               ..............
                              }
                          
                          });
                          

                          【讨论】:

                            【解决方案18】:

                            在您定义 $middlewareGroups 时也可能出现这种情况

                            您应该使用以下格式:

                            protected $middlewareGroups = [
                                'web'   => [],
                                'api'   => [
                                    'web',
                                    'throttle:500,1'
                                ],
                                'basic' => [
                                    'auth:basic',
                                ]
                            ];
                            

                            【讨论】:

                              【解决方案19】:

                              我实际上遇到了这个错误并且找不到解决方案。我实际上最终没有做一个ajax请求。我不知道这个问题是由于这是我服务器上的子域还是什么。这是我的 jquery。

                                          $('#deleteMeal').click(function(event) {
                                              var theId = $(event.currentTarget).attr("data-mealId");
                                                $(function() {
                                                  $( "#filler" ).dialog({
                                                    resizable: false,
                                                    height:140,
                                                    modal: true,
                                                    buttons: {
                                                    "Are you sure you want to delete this Meal? Doing so will also delete this meal from other users Saved Meals.": function() {
                                                         $('#deleteMealLink').click();
                              //                         jQuery.ajax({
                              //                              url : 'http://www.mealog.com/mealtrist/meals/delete/' + theId,
                              //                              type : 'POST',
                              //                              success : function( response ) {
                              //                                  $("#container").replaceWith("<h1 style='color:red'>Your Meal Has Been Deleted</h1>");
                              //                              }
                              //                          });
                                                      // similar behavior as clicking on a link
                                                         window.location.href = 'http://www.mealog.com/mealtrist/meals/delete/' + theId;
                                                        $( this ).dialog( "close" );
                                                      },
                                                      Cancel: function() {
                                                        $( this ).dialog( "close" );
                                                      }
                                                    }
                                                  });
                                                });
                                              });
                              

                              所以我实际上设置了一个锚点来访问我的 API,而不是执行发布请求,这是我认为大多数应用程序所做的。

                                <p><a href="http://<?php echo $domain; ?>/mealtrist/meals/delete/{{ $meal->id }}" id="deleteMealLink" data-mealId="{{$meal->id}}" ></a></p>
                              

                              【讨论】:

                                【解决方案20】:

                                我只是在表单中使用 @csrf 并且它工作正常

                                【讨论】:

                                  【解决方案21】:

                                  我最近总是遇到这个错误。确保在引用值时使用更具体的选择器。例如,而不是 $('#firstname') 使用 $('form').find('#firstname');

                                  【讨论】:

                                  • ids 无论如何都应该是唯一的,所以你不能得到比#firstname 选择器更具体的东西。
                                  • 好吧..在我的情况下..我确实有多个模态..这就是冲突开始的地方
                                  • 那是无效的 HTML。来自the docs:“id 属性指定其元素的唯一标识符 (ID)。该值在元素的主子树中的所有 ID 中必须是唯一的,并且必须包含至少一个字符。”网页中元素的主子树就是页面。
                                  • Ow.. 谢谢你.. 我认为这会导致错误。顺便说一句.. $('#myform1').find('#firstname') 与 $('#myform2').find('#firstname') 不同...所以我只使用时出错('#firstname').. 这就是我说你需要更具体的原因。
                                  【解决方案22】:

                                  我与这个错误斗争了几天。我尝试了所有建议,但没有任何效果。

                                  然后做: php artisan cache:clear 我收到一条非常奇怪的错误消息: Failed to clear cache. Make sure you have the appropriate permissions. 我不得不手动删除 /application/storage/framework/cache/data 目录中的所有文件。然后我设法清除了缓存。

                                  然后csrf-error就消失了。我不知道为什么,但我曾经是一个快乐的人……

                                  【讨论】:

                                    猜你喜欢
                                    • 2014-11-04
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2017-01-25
                                    • 2020-05-10
                                    • 1970-01-01
                                    • 2017-05-02
                                    • 2020-01-28
                                    • 2016-07-26
                                    相关资源
                                    最近更新 更多