Laravel csrf token mismatch for ajax POST Request

2020-01-23 03:05发布

I am trying to delete data from database via ajax.

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:

$('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...

11条回答
戒情不戒烟
2楼-- · 2020-01-23 03:23

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-token You may like to use it.

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

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

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

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

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.

And here read cookie function:

   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;
    }
查看更多
何必那么认真
3楼-- · 2020-01-23 03:28

You should include a hidden CSRF (cross site request forgery) token field in the form so that the CSRF protection middleware can validate the request.

Laravel automatically generates a CSRF "token" for each active user session managed by the application. This token is used to verify that the authenticated user is the one actually makin gthe requests to the application.

So when doing ajax requests, you'll need to pass the csrf token via data parameter. Here's the sample code.

var request = $.ajax({
    url : "http://localhost/some/action",
    method:"post",
    data : {"_token":"{{ csrf_token() }}"}  //pass the CSRF_TOKEN()
  });
查看更多
虎瘦雄心在
4楼-- · 2020-01-23 03:30

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:

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>
查看更多
成全新的幸福
5楼-- · 2020-01-23 03:33

I actually had this error and could not find a solution. I actually ended up not doing an ajax request. I don't know if this issue was due to this being sub domain on my server or what. Here's my 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" );
                        }
                      }
                    });
                  });
                });

So I actually set up an anchor to go to my API rather than doing a post request, which is what I figure most applications do.

  <p><a href="http://<?php echo $domain; ?>/mealtrist/meals/delete/{{ $meal->id }}" id="deleteMealLink" data-mealId="{{$meal->id}}" ></a></p>
查看更多
Luminary・发光体
6楼-- · 2020-01-23 03:37

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

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

And the JQUery :

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

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

查看更多
我欲成王,谁敢阻挡
7楼-- · 2020-01-23 03:40

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

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
查看更多
登录 后发表回答