Mã thông báo csrf của Laravel không khớp đối với Yêu cầu POST ajax


113

Tôi đang cố gắng xóa dữ liệu khỏi cơ sở dữ liệu thông qua ajax.

HTML:

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

Mã ajax của tôi:

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

Đây là truy vấn của tôi để tìm nạp dữ liệu từ cơ sở dữ liệu ...

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

Nhưng khi tôi nhấp vào Xóa liên kết dữ liệu không bị xóa và hiển thị csrf_token không khớp ...



bạn nên thêm thành công và lỗi vào mã ajax của mình. lỗi sẽ hiển thị vấn đề. stackoverflow.com/questions/45668337/…
reza jafari

Câu trả lời:


176

Bạn phải thêm dữ liệu trong yêu cầu ajax của mình. Tôi hy vọng như vậy nó sẽ thành công.

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

32
Điều gì sẽ xảy ra nếu hàm ajax được đặt trong .jstệp?
Brane

1
Nó không hoạt động trên Laravel 5.7. câu trả lời của zarpio là đúng.
Omar Murcia

1
@Brane gửi mã thông báo như một param trong hàm
Abdelalim Hassouna

Điều này không hoạt động trong Laravel 5.8. Nó vẫn cho biết mã thông báo không khớp. Kiểm tra câu trả lời của tôi bên dưới để có giải pháp đơn giản
Gjaa

laravel có thay đổi mã thông báo csrf sau khi yêu cầu json không? bạn có cần gửi cái mới đến trang chính không?
davefrassoni 20/09/2018

184

Cách tốt nhất để giải quyết vấn đề này "X-CSRF-TOKEN" là thêm mã sau vào bố cục chính của bạn và tiếp tục thực hiện các cuộc gọi ajax của bạn một cách bình thường:

Trong tiêu đề

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

Trong kịch bản

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

5
Cảm ơn anh bạn. Đây là một giải pháp tròn trịa hơn! Bằng cách này, bạn chỉ cần thiết lập nó một lần và sau đó chỉ cần viết mã $ .ajax bình thường của bạn.
pkid169, 27/09/17

4
Đây là giải pháp tốt hơn vì bạn có thể sử dụng nó bên trong .jsfile
Adam

3
Câu trả lời tốt nhất cho đến nay. Cảm ơn.
Paul Denisevich,

nếu "toàn cầu: sai" thì sao?
Michel

Làm cách nào để cập nhật csrf sau mỗi cuộc gọi? cuộc gọi đầu tiên hoạt động tốt, các cuộc gọi con không thành công do mã thông báo CSRF.
Jjsg08 Ngày

28

Tôi nghĩ tốt hơn nên đặt mã thông báo vào biểu mẫu và nhận mã thông báo này bằng id

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

Và JQUery:

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

theo cách này, JS của bạn không cần phải có trong các tệp phiến của bạn.


25

Tôi vừa thêm headers:vào cuộc gọi ajax:

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

trong quan điểm:

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

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

hàm 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>

trong bộ điều khiển:

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

trong route.php

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

1
thêm tiêu đề vào lệnh gọi ajax đã giúp tôi.
Chaudhry Waqas

1
Đây là câu trả lời tốt nhất vì nó không đòi hỏi hoạt Javascript để được trong một tập tin lưỡi (trừ khi bạn muốn nó trong một file lưỡi, nhưng sau đó nó đã được trả lại mỗi khi ai đó nói đến trang đó)
Zachary Weixelbaum

11

Nếu bạn đang sử dụng tệp mẫu, bạn có thể đặt metathẻ của mình vào phần đầu section(hoặc bất cứ tên gì bạn đặt tên nó) chứa metathẻ của bạn .

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

Điều tiếp theo, bạn cần đặt headersthuộc tính cho của bạn ajax(trong ví dụ của tôi, tôi đang sử dụng datatablevới xử lý phía máy chủ:

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

Đây là datatableví dụ ajax đầy đủ :

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

Sau khi làm điều này, bạn sẽ nhận được yêu cầu 200 statuscủa mình ajax.


6

Biết rằng có một cookie X-XSRF-TOKEN được thiết lập để thuận tiện. Framework như Angular và các framework khác đặt nó theo mặc định. Kiểm tra điều này trong tài liệu https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token Bạn có thể muốn sử dụng nó.

Cách tốt nhất là sử dụng meta, trong trường hợp cookie bị vô hiệu hóa.

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

Dưới đây là cách meta được đề xuất (bạn có thể đặt trường theo bất kỳ cách nào, nhưng meta rất tốt):

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

Lưu ý việc sử dụng decodeURIComponent() , nó giải mã từ định dạng uri được sử dụng để lưu trữ cookie. [nếu không, bạn sẽ nhận được một ngoại lệ tải trọng không hợp lệ trong laravel].

Đây là phần về cookie csrf trong tài liệu để kiểm tra: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

Cũng ở đây cách laravel (bootstrap.js) đặt nó cho axios theo mặc định:

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

bạn có thể đi kiểm tra resources/js/bootstrap.js.

Và đây đọc hàm 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;
    }

5

Thêm một idvào metaphần tử giữ mã thông báo

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

Và sau đó bạn có thể lấy nó trong Javascript của mình

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

1
Nếu bạn không muốn thêm id, chỉ cần sử dụng: $ ("[name = csrf-token]"). Attr ("content") để thay thế. Nó sẽ tìm nạp phần tử bên phải theo thuộc tính name.
Pedro Sousa

3

nếu bạn đang sử dụng jQuery để gửi Bài đăng AJAX, hãy thêm mã này vào tất cả các chế độ xem:

$( 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 thêm cookie XSRF vào tất cả các yêu cầu và chúng tôi tự động nối nó vào tất cả các yêu cầu AJAX ngay trước khi gửi.

Bạn có thể thay thế hàm getCookie nếu có một hàm khác hoặc plugin jQuery để làm điều tương tự.


1

Đối với Laravel 5.8, việc đặt thẻ meta csrf cho bố cục của bạn và đặt tiêu đề yêu cầu cho csrf trong cài đặt ajax sẽ không hoạt động nếu bạn đang sử dụng ajax để gửi biểu mẫu đã bao gồm _token trường đầu vào được tạo bởi công cụ tạo khuôn lưỡi Laravel.

Bạn phải bao gồm mã thông báo csrf đã được tạo từ biểu mẫu với yêu cầu ajax của mình bởi vì máy chủ sẽ mong đợi nó chứ không phải mã trong thẻ meta của bạn.

Ví dụ, đây là cách trường _tokenđầu vào do Blade tạo ra trông giống như sau:

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

Sau đó, bạn gửi biểu mẫu của mình với ajax như sau:

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

Mã thông báo csrf trong tiêu đề meta chỉ hữu ích khi bạn đang gửi biểu mẫu mà không có _tokentrường nhập do Blade tạo .


1

ai đang gặp vấn đề với câu trả lời được chấp nhận @Deepak saini, hãy thử xóa

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

cho cuộc gọi ajax.

sử dụng

dataType:"json",

0

Tôi thực sự đã gặp lỗi này và không thể tìm ra giải pháp. Tôi thực sự đã không thực hiện một yêu cầu ajax. Tôi không biết sự cố này có phải do đây là miền phụ trên máy chủ của tôi hay không. Đây là jquery của tôi.

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

Vì vậy, tôi thực sự thiết lập một mỏ neo để truy cập API của mình thay vì thực hiện một yêu cầu đăng, đó là điều mà tôi nghĩ hầu hết các ứng dụng đều làm.

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

0

Bạn nên bao gồm trường mã thông báo CSRF (giả mạo yêu cầu trang web chéo) ẩn trong biểu mẫu để phần mềm trung gian bảo vệ CSRF có thể xác thực yêu cầu.

Laravel tự động tạo "mã thông báo" CSRF cho mỗi phiên người dùng đang hoạt động do ứng dụng quản lý. Mã thông báo này được sử dụng để xác minh rằng người dùng đã xác thực là người thực sự yêu cầu ứng dụng.

Vì vậy, khi thực hiện các yêu cầu ajax, bạn sẽ cần chuyển mã thông báo csrf qua tham số dữ liệu. Đây là mã mẫu.

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

0

Tôi chỉ sử dụng @csrf bên trong biểu mẫu và nó hoạt động tốt

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.