Token csrf Laravel tidak cocok untuk Permintaan POST ajax

114

Saya mencoba menghapus data dari database melalui ajax.

HTML:

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

Kode ajax saya:

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

Ini adalah permintaan saya untuk mengambil data dari database ...

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

Tetapi ketika saya mengklik Hapus data tautan tidak dihapus dan menunjukkan ketidakcocokan csrf_token ...

Ashish Singh
sumber
Anda harus menambahkan kesuksesan dan kesalahan ke kode ajax Anda. kesalahan akan menunjukkan masalahnya. stackoverflow.com/questions/45668337/…
reza jafari

Jawaban:

177

Anda harus menambahkan data dalam permintaan ajax Anda. Saya berharap ini akan berhasil.

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
Deepak saini
sumber
32
Bagaimana jika fungsi ajax terletak di .jsfile?
Brane
1
Ini tidak berfungsi di Laravel 5.7. Jawaban zarpio benar.
Omar Murcia
1
@Brane mengirim token sebagai param dalam fungsinya
Abdelalim Hassouna
Ini tidak berfungsi di Laravel 5.8. Masih tertulis ketidakcocokan token. Periksa jawaban saya di bawah ini untuk solusi sederhana
Gjaa
apakah laravel mengubah token csrf setelah permintaan json? apakah Anda perlu mengirim yang baru ke halaman utama?
davefrassoni
187

Cara terbaik untuk mengatasi masalah ini "X-CSRF-TOKEN" adalah dengan menambahkan kode berikut ke layout utama Anda, dan terus melakukan panggilan ajax seperti biasa:

Di header

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

Dalam naskah

<script type="text/javascript">
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>
zarpio
sumber
5
Terima kasih sobat. Ini adalah solusi yang lebih baik! Dengan cara ini Anda hanya mengaturnya sekali dan setelah itu langsung saja menulis kode $ .ajax normal Anda.
pkid169
4
Ini adalah solusi yang lebih baik karena Anda dapat menggunakannya di dalam .jsfile
Adam
3
Jawaban terbaik sejauh ini. Terima kasih.
Paul Denisevich
bagaimana jika "global: false"?
Michel
1
Bagaimana csrf dapat diperbarui setelah setiap panggilan? panggilan pertama berfungsi dengan baik, panggilan sub-sekuen gagal karena token CSRF.
Jjsg08
28

Saya pikir lebih baik letakkan token di formulir, dan dapatkan token ini dengan id

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

Dan JQUery:

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

dengan cara ini, JS Anda tidak perlu ada di file blade Anda.

cmnardi.dll
sumber
25

Saya baru saja menambahkan headers:dalam panggilan ajax:

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

dalam penglihatan:

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

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

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

dalam pengontrol:

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

di routes.php

Route::post('ajax', 'AjaxController@call');
lewis4u
sumber
1
menambahkan header ke panggilan ajax membantu saya.
Chaudhry Waqas
1
Ini adalah jawaban terbaik karena tidak memerlukan JavaScript dalam file blade (kecuali jika Anda menginginkannya dalam file blade, tetapi kemudian ditampilkan setiap kali seseorang
membuka
12

Jika Anda menggunakan file template, Anda dapat meletakkan metatag Anda di head section(atau apa pun namanya) yang berisi metatag Anda .

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

Hal berikutnya, Anda perlu meletakkan headersatribut ke Anda ajax(dalam contoh saya, saya menggunakan datatabledengan pemrosesan sisi server:

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

Berikut datatablecontoh lengkap 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);
           }
        }
    });

Setelah melakukan ini, Anda harus mendapatkan permintaan 200 statusAnda ajax.

Brane
sumber
6

Ketahuilah bahwa ada cookie X-XSRF-TOKEN yang diatur untuk kenyamanan. Kerangka kerja seperti Angular dan lainnya mengaturnya secara default. Periksa ini di dokumen https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token Anda mungkin ingin menggunakannya.

Cara terbaik adalah menggunakan meta, jika cookie dinonaktifkan.

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

Berikut cara meta yang disarankan (Anda dapat meletakkan bidang dengan cara apa pun, tetapi meta cukup bagus):

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

Catat penggunaannya decodeURIComponent(), ini diterjemahkan dari format uri yang digunakan untuk menyimpan cookie. [jika tidak, Anda akan mendapatkan pengecualian muatan yang tidak valid di laravel].

Di sini bagian tentang cookie csrf di dokumen untuk diperiksa: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

Juga di sini bagaimana laravel (bootstrap.js) mengaturnya untuk axios secara 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');
} 

kamu bisa pergi memeriksanya resources/js/bootstrap.js.

Dan di sini membaca fungsi 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;
    }
Mohamed Allal
sumber
5

Tambahkan idke metaelemen yang menyimpan token

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

Dan kemudian Anda bisa mendapatkannya di Javascript Anda

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

EDIT: Cara yang lebih mudah tanpa mengubah metagaris.

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

Atau

data : { 
    _token: @json(csrf_token()), 
}

Terima kasih kepada @ martin-hartmann

Gjaa
sumber
2
Jika Anda tidak ingin menambahkan id, cukup gunakan: $ ("[name = csrf-token]"). Attr ("content") sebagai gantinya. Ini akan mengambil elemen yang tepat dengan atribut name.
Pedro Sousa
1
Ini juga memungkinkan untuk hanya beriklan di bidang data: data: {"_token": "{{csrf_token ()}}" // berikan CSRF_TOKEN ()},
Martin Hartmann
3

jika Anda menggunakan jQuery untuk mengirim Postingan AJAX, tambahkan kode ini ke semua tampilan:

$( 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 menambahkan cookie XSRF ke semua permintaan, dan kami secara otomatis menambahkannya ke semua permintaan AJAX sebelum mengirim.

Anda bisa mengganti fungsi getCookie jika ada fungsi lain atau plugin jQuery untuk melakukan hal yang sama.

AMIB
sumber
1

Untuk Laravel 5.8, mengatur tag meta csrf untuk layout Anda dan mengatur header permintaan untuk csrf dalam pengaturan ajax tidak akan berfungsi jika Anda menggunakan ajax untuk mengirimkan formulir yang sudah menyertakan _token kolom masukan yang dihasilkan oleh mesin template blade Laravel.

Anda harus menyertakan token csrf yang sudah dibuat dari formulir dengan permintaan ajax Anda karena server akan mengharapkannya dan bukan yang ada di tag meta Anda.

Misalnya, seperti inilah kolom _tokeninput yang dihasilkan oleh Blade:

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

Anda kemudian mengirimkan formulir Anda dengan ajax seperti ini:

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

Token csrf di header meta hanya berguna saat Anda mengirimkan formulir tanpa _tokenbidang masukan yang dibuat oleh Blade .

Udo E.
sumber
1

yang bermasalah dengan jawaban diterima @Deepak saini, coba hapus

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

untuk panggilan ajax.

menggunakan

dataType:"json",
Mrudul Addipalli
sumber
0

Saya sebenarnya mengalami kesalahan ini dan tidak dapat menemukan solusi. Saya sebenarnya akhirnya tidak melakukan permintaan ajax. Saya tidak tahu apakah masalah ini disebabkan oleh sub-domain ini di server saya atau apa. Ini jquery saya.

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

Jadi saya sebenarnya menyiapkan jangkar untuk masuk ke API saya daripada melakukan permintaan posting, yang menurut saya sebagian besar aplikasi lakukan.

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

Anda harus menyertakan bidang token CSRF (permintaan pemalsuan lintas situs) yang tersembunyi dalam formulir sehingga middleware perlindungan CSRF dapat memvalidasi permintaan tersebut.

Laravel secara otomatis menghasilkan "token" CSRF untuk setiap sesi pengguna aktif yang dikelola oleh aplikasi. Token ini digunakan untuk memverifikasi bahwa pengguna yang diautentikasi adalah yang benar-benar membuat permintaan ke aplikasi.

Jadi saat melakukan permintaan ajax, Anda harus meneruskan token csrf melalui parameter data. Berikut kode contoh.

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

Saya hanya menggunakan @csrf di dalam formulir dan berfungsi dengan baik

diri
sumber