ChatGPT解决这个技术问题 Extra ChatGPT

ajax POST请求的Laravel csrf令牌不匹配

我正在尝试通过 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 不匹配时...

您应该将成功和错误添加到您的 ajax 代码中。错误将显示问题。 stackoverflow.com/questions/45668337/…
使用以下链接 Laravel official site

z
zarpio

解决此问题“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 文件中使用它
如果“全局:假”怎么办?
每次通话后如何更新 csrf?第一次通话效果很好,由于 CSRF 令牌,后续通话失败。
@zarpio 我正在使用相同的方法。但是,在我的 ajax 调用中出现了令牌不匹配错误。请帮助我。
D
Deepak saini

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

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

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

我刚刚在 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');

拉拉维尔 8^

Route::post('ajax', [AjaxController::class, 'call']);

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

我认为最好将令牌放入表单中,并通过 id 获取此令牌

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

和 JQUEy :

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

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


B
Brane

如果您使用模板文件,则可以将 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


G
Gjaa

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() },
M
Mohamed Allal

知道有一个 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 中得到一个无效的负载异常]。

这里是关于文档中要检查的 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;
    }

V
Vignesh

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

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

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

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

A
AMIB

如果您使用 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 函数。


M
Mrudul Addipalli

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

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

用于ajax调用。

利用

dataType:"json",

S
Sahil Jain

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

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

M
Michael Asefon

如果您正在使用 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) }
        });

N
Nava Bogatee

您应该在表单中包含一个隐藏的 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()
  });

U
Udo E.

xxxxxxx旧答案已删除xxxxxxx

澄清/更新

元标头中的 csrf 令牌用于 session management

Laravel 会为应用程序管理的每个活动用户会话自动生成一个 CSRF “令牌”。

它与包含在以下内容中的值相同:

@csrf 指令在表单中或 Blade 模板中的任何其他位置(这会生成 _token 隐藏输入字段)。 csrf_token() 全局辅助函数在控制器或刀片模板中的任何位置使用。

重要的

对于尚未经过身份验证的会话,CSRF 令牌为每个服务页面重新生成/不同 - 即为每个加载的页面生成新的会话数据。对于经过身份验证的会话,CSRF 令牌对于所有页面都是相同的 - 即会话数据在所有加载的页面中保持不变。

结论

通过以下方式在 Ajax 请求中包含 CSRF 令牌:

来自元标头或生成的隐藏 _token 输入字段 - 在使用表单发送 Ajax POST 请求时很有用:

<script> 
    $(document).ready(function() { 
        let token = $('meta[name="csrf_token"]').attr('content');
        // let token = $('form').find('input[name="_token"]').val(); // this will also work
        let myData = $('form').find('input[name="my_data"]').val();
        $('form').submit(function() { 
            $.ajax({ 
                type:'POST', 
                url:'/ajax', 
                data: {_token: token, my_data: myData}
                // other ajax settings
            }); 
            return false;
        }); 
    }); 
</script>

在 Blade 模板的隐藏元素中调用 csrf_token() 并在 js 中获取令牌 - 在发送没有表单的 Ajax POST 请求时很有用:

刀:

<span id='csrf' style='display:none'>{{ csrf_token() }}<span>

JavaScript:

<script> 
    $(document).ready(function() { 
        let token = $('#csrf').html();
        $.ajax({ 
            type:'POST', 
            url:'/ajax', 
            data: {_token: token, my_data: 'john'}
            // other ajax settings
        }); 
    }); 
</script>

m
myself

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


J
Joundill

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


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

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

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

r
rameezmeans

在新的 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);
        }
    });

A
Ashish Singh

简单地将 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() {
     ..............
    }

});

K
Kolya Slisarenko

当您定义 $middlewareGroups 时,也可能存在这种情况

您应该使用以下格式:

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

g
glinda93

如果您将 laravel 从 5 升级到 8,并遇到此错误,请将以下内容添加到 app/Http/Middleware/VerifyCsrfToken.php

public static function serialized()
{
    return true;
}

M
MUHINDO

在刀片文件的脚本标记中,这样做以生成有效的表单令牌并在 jQuery 中获取它

<script>
    $(document).ready(function() {
        $("#my-upload-button").click(function() {

            var token = "{{ csrf_token() }}";//here getting token from blade

            $.post('my-url', {
                    _token: token,
                    datra: ...
                },
                function(data) {
                    alert(data); 
                });
        });         

});


Y
Yasser CHENIK

我仅通过删除 processData: false 为我解决了这个问题

$.ajax({
                url: '{{ route('login') }}' ,
                method: 'POST',
                data: {
                    _token : {{ csrf_token() }},
                    data : other_data,
                },
                cache: false,
                //processData: false, // remove this

                ...

                success: function(res){
                   ...
                }
});

E
Earth Lander

在您的主页 (someViewsName.blade.php) 中,声明一个全局变量

<script>
    var token = "{{ csrf_token() }}";
</script>

<script src="/path/to/your_file.js"></script>

然后,在 your_file.js

$.ajax({
        type: "post",
        url: "http://your.url/end/point",
        data: {
                _token:token,
                data:your_data,
              },
        dataType: "json",
        success: function (response) {
            // code some stuff
        }
    });

D
Dlaugh14

我实际上有这个错误并且找不到解决方案。我实际上最终没有做一个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>