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 _ 令牌不匹配..。

525999 次浏览

你必须添加 资料在你的 Ajax 请求。我希望这样会工作。

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

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

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

还有 JQuery:

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

这样的话,你的 JS 就不需要出现在你的刀片文件里了。

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

路线

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

幼虫8 ^

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

我实际上有这个错误,无法找到一个解决方案。实际上我没有做 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 的锚,而不是执行 post 请求,我认为大多数应用程序都是这样做的。

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

解决这个问题“ 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>

如果您使用的是模板文件,那么您可以将您的 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);
}
}
});

完成此操作后,您应该获得 200 status以满足 ajax请求。

如果您使用 jQuery 发送 AJAX Posts,请将以下代码添加到所有视图:

$( 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 函数。

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

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

因此,在执行 ajax 请求时,需要通过数据参数传递 Csrf 令牌

这是示例代码。

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

要知道,有一个 X-XSRF-TOKEN cookie 是为了方便而设置的。像 Angular 这样的框架默认设置它。请在文档 < a href = “ https://laravel.com/docs/5.7/csrf # csrf-x-xsrf-token”rel = “ norefrer”> https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token 中查看 你可能会喜欢用它。

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

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

这里推荐的 meta 方法(你可以把字段放在任何地方,但 meta 是非常好的) :

$.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;
}

Xxxxxxx旧答案已删除xxxxxxx

澄清/更新

Meta 头中的 csrf 标记用于 会议管理

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

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

  1. 表单中的 @csrf指令或 Blade 模板中的其他任何地方(这将生成 _token隐藏输入字段)。
  2. csrf_token()全局助手函数用于控制器或 Blade 模板中的任何位置。

很重要

  1. 对于尚未通过身份验证的 没有会话,CSRF 令牌针对每个服务的页面重新生成/不同-即为每个加载的页面生成新的会话数据。
  2. 对于经过身份验证的会话,CSRF 令牌对于所有页面都是相同的-也就是说,会话数据在所有加载的页面上维护。

结论

以下列方式将 CSRF 令牌包含在 Ajax 请求中:

  1. 来自 meta 头或生成的隐藏 _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>
  1. 在 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>

向保存标记的 meta元素添加一个 id

<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

我只是在表单中使用@csrf,它工作得很好

谁曾经有问题的接受答案@Deepak saini,试图删除

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

给 Ajax 打电话。

使用

dataType:"json",

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

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

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

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

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

伙计们,你们只需要在任何地方这样做。在 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);
}
});

如果你正在从事 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) }
});

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

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

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

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

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


});

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

你应使用以下格式:

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

如果你正在从5升级到8,面对这个错误,添加以下到 app/Http/Middleware/VerifyCsrfToken.php:

public static function serialized()
{
return true;
}

在刀片服务器文件的 script 标记中,这样做可以生成一个有效的表单标记,并在 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);
});
});

我这个问题是解决了我只是删除 processData: false

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


...


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

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

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


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

然后,在您的 _ 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
}
});

哈哈,我尝试了同样的问题每一个解决方案但是在那之后再次检查 env 并且有一个标志为真导致了这个问题,

SESSION_SECURE_COOKIE=true

删除这一行,它将修复的问题。