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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32738763/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 23:10:28  来源:igfitidea点击:

Laravel csrf token mismatch for ajax POST Request

phpjqueryajaxlaravel

提问by Ashish Singh

I am trying to delete data from database via ajax.

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

HTML:

HTML:

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

My ajax code:

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

This is my query to fetch data from database...

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

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

But when i click on Delete link data not deleted and show csrf_token mismatch...

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

回答by zarpio

The best way to solve this problem "X-CSRF-TOKEN" is to add the following code to your main layout, and continue making your ajax calls normally:

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

In header

在标题中

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

In script

在脚本中

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

回答by Deepak saini

You have to add datain your ajax request. I hope so it will be work.

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

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

回答by cmnardi

I think is better put the token in the form, and get this token by id

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

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

And the JQUery :

和 JQUEry :

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

this way, your JS don't need to be in your blade files.

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

回答by lewis4u

I just added headers:in ajax call:

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

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

in view:

鉴于:

<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 function:

阿贾克斯功能:

<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>

in controller:

在控制器中:

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

in routes.php

在routes.php

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

回答by Brane

If you are using template files, than you can put your metatag in the head section(or whatever you name it) which contain your metatags.

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

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

Next thing, you need to put the headersattribute to your ajax(in my example, I am using datatablewith server-side processing:

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

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

Here is the full datatableajax example:

这是完整的datatableajax 示例:

$('#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);
           }
        }
    });

After doing this, you should get 200 statusfor your ajaxrequest.

这样做之后,您应该得到200 status您的ajax请求。

回答by Mohamed Allal

Know that there is an X-XSRF-TOKEN cookie that is set for convenience. Framework like Angular and others set it by default. Check this in the doc https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-tokenYou may like to use it.

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

The best way is to use the meta, case the cookies are deactivated.

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

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

Here the recommended meta way (you can put the field any way, but meta is quiet nice):

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

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

Note the use of decodeURIComponent(), it's decode from uri format which is used to store the cookie. [otherwise you will get an invalid payload exception in laravel].

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

Here the section about the csrf cookie in the doc to check : https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

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

Also here how laravel (bootstrap.js) is setting it for axios by default:

同样在这里,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');
} 

you can go check resources/js/bootstrap.js.

你可以去检查一下resources/js/bootstrap.js

And here read cookie function:

在这里读取 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;
    }

回答by Gjaa

Add an idto the metaelement that holds the token

idmeta包含令牌的元素添加一个

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

And then you can get it in your Javascript

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

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

回答by AMIB

if you are using jQuery to send AJAX Posts, add this code to all views:

如果您使用 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, '\'); };
    var match = document.cookie.match(RegExp('(?:^|;\s*)' + escape(name) + '=([^;]*)'));
    return match ? match[1] : null;
}

Laravel adds a XSRF cookie to all requests, and we automatically append it to all AJAX requests just before submit.

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

You may replace getCookie function if there is another function or jQuery plugin to do the same thing.

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

回答by Udo E.

For Laravel 5.8, setting the csrf meta tag for your layout and setting the request header for csrf in ajax settings won't work if you are using ajax to submit a form that already includes a _tokeninput field generated by the Laravel blade templating engine.

对于 Laravel 5.8,如果您使用 ajax 提交已经包含_token由 Laravel 刀片模板引擎生成的输入字段的表单,则为您的布局设置 csrf 元标记和在 ajax 设置中设置 csrf 的请求标头将不起作用。

You must include the already generated csrf token from the form with your ajax request because the server would be expecting it and not the one in your meta tag.

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

For instance, this is how the _tokeninput field generated by Blade looks like:

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

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

You then submit your form with ajax like this:

然后,您使用 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>

The csrf token in the meta header is only useful when you are submitting a form without a Blade generated _tokeninput field.

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

回答by myself

I just use @csrf inside the form and its working fine

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