Ajax POST İsteği için Laravel csrf token uyuşmazlığı


122

Ajax ile veri tabanından veri silmeye çalışıyorum.

HTML:

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

Ajax kodum:

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

Bu, veritabanından veri alma sorgum ...

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

Ancak silinmemiş bağlantı verilerini sil seçeneğine tıkladığımda ve csrf_token uyuşmazlığını gösterdiğimde ...



ajax kodunuza başarı ve hata eklemelisiniz. hata sorunu gösterecektir. stackoverflow.com/questions/45668337/…
reza jafari

Yanıtlar:


190

Ajax isteğinize veri eklemelisiniz . Umarım işe yarar.

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

34
Ya ajax işlevi .jsdosyada bulunuyorsa?
Brane

2
Laravel 5.7'de çalışmıyor. zarpio'nun cevabı doğru.
Omar Murcia

1
@Brane, jetonu işlevde bir param olarak gönder
Abdelalim Hassouna

Bu Laravel 5.8'de çalışmaz. Hala belirteç uyuşmazlığı olduğunu söylüyor. Basit bir çözüm için aşağıdaki cevabımı kontrol edin
Gjaa

laravel bir json isteğinden sonra csrf belirtecini değiştirir mi? yenisini ana sayfaya göndermeniz gerekiyor mu?
davefrassoni

202

Bu sorunu çözmenin en iyi yolu "X-CSRF-TOKEN" aşağıdaki kodu ana düzeninize eklemek ve ajax çağrılarınızı normal şekilde yapmaya devam etmektir:

Başlıkta

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

Senaryoda

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

6
Teşekkürler dostum. Bu daha kapsamlı bir çözümdür! Bu şekilde sadece bir kez kurarsınız ve daha sonra normal $ .ajax kodunuzu yazmaya devam edersiniz.
pkid169

4
Bu daha iyi bir çözüm çünkü onu .jsdosyaların içinde kullanabilirsiniz
Adam

3
Şimdiye kadarki en iyi cevap. Teşekkürler.
Paul Denisevich

ya "genel: yanlış" ise?
Michel

3
Her aramadan sonra csrf nasıl güncellenebilir? ilk arama harika çalışıyor, alt bölüm aramaları CSRF belirteci nedeniyle başarısız oluyor.
Jjsg08

28

Bence jetonu forma koymak ve bu jetonu kimliğe göre almak daha iyidir

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

Ve JQUery:

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

bu şekilde, JS'nizin blade dosyalarınızda olması gerekmez.


27

headers:Ajax çağrısına ekledim :

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

görünümünde:

<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 işlevi:

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

denetleyicide:

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

route.php içinde

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

1
ajax aramasına başlık eklemek bana yardımcı oldu.
Chaudhry Waqas

1
Bu en iyi cevaptır çünkü JavaScript'in bir blade dosyasında olmasını gerektirmez (bir blade dosyasında istemediğiniz sürece, ancak o sayfaya birisi her geldiğinde işlenir)
Zachary Weixelbaum

12

Şablon dosyaları kullanıyorsanız, metaetiketinizi section, metaetiketlerinizi içeren başa (veya ne adlandırırsanız adlandırın) koyabilirsiniz .

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

Sonra, headersözniteliği sizin için koymanız gerekir ajax(benim örneğimde, datatablesunucu tarafı işlemeyle kullanıyorum:

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

İşte tam datatableajax örneği:

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

Bunu yaptıktan sonra, almalısınız 200 statussizin için ajaxistek.


6

Kolaylık sağlamak için ayarlanmış bir X-XSRF-TOKEN tanımlama bilgisi olduğunu bilin. Angular ve diğerleri gibi çerçeve varsayılan olarak onu ayarlar. Bunu https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token belgesinde kontrol edin Kullanmak isteyebilirsiniz.

En iyi yol, çerezlerin devre dışı bırakılması durumunda meta kullanmaktır.

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

İşte önerilen meta yol (alanı istediğiniz gibi koyabilirsiniz, ancak meta oldukça güzel):

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

Kullanımına dikkat decodeURIComponent()çerez saklamak için kullanılır uri biçiminden 's şifresini çözmek,. [aksi takdirde laravel'de geçersiz bir yük istisnası alırsınız].

Burada, belgede kontrol edilecek csrf çereziyle ilgili bölüm: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

Ayrıca laravel'in (bootstrap.js) bunu axios için varsayılan olarak nasıl ayarladığını burada:

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

gidip kontrol edebilirsiniz resources/js/bootstrap.js.

Ve burada çerez işlevini okuyun:

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

6

Bir ekleme idiçin metabelirteç tutan elemanın

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

Ve sonra bunu Javascript'inize alabilirsiniz

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

DÜZENLEME: metaÇizgiyi değiştirmeden daha kolay yol .

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

Veya

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

@ Martin-hartmann'a teşekkürler


2
Bir id eklemek istemiyorsanız, bunun yerine $ ("[name = csrf-token]"). Attr ("içerik") kullanın. İsim niteliğine göre doğru öğeyi getirecektir.
Pedro Sousa

1
Veri alanına yalnızca bir reklam eklemek de mümkündür: data: {"_token": "{{csrf_token ()}}" // CSRF_TOKEN ()} 'i iletin,
Martin Hartmann

3

AJAX Gönderileri göndermek için jQuery kullanıyorsanız, bu kodu tüm görünümlere ekleyin:

$( 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, tüm isteklere bir XSRF çerezi ekler ve bunu göndermeden hemen önce tüm AJAX isteklerine otomatik olarak ekleriz.

Aynı şeyi yapmak için başka bir işlev veya jQuery eklentisi varsa getCookie işlevini değiştirebilirsiniz.


2

Kabul edilen cevap @Deepak saini ile sorun yaşayan kimse, kaldırmayı deneyin

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

ajax çağrısı için.

kullanım

dataType:"json",

1

Laravel 5.8 için, mizanpajınız için csrf meta etiketini ayarlamak ve ajax ayarlarında csrf için istek başlığını ayarlamak _token, Laravel blade şablon oluşturma motoru tarafından oluşturulan bir giriş alanı içeren bir form göndermek için ajax kullanıyorsanız çalışmayacaktır .

Formdan önceden oluşturulmuş csrf belirtecini ajax isteğinize dahil etmelisiniz çünkü sunucu meta etiketinizdeki değil, sunucu bunu bekler.

Örneğin, _tokenBlade tarafından oluşturulan giriş alanı şu şekilde görünür:

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

Daha sonra formunuzu aşağıdaki gibi bir ajax ile gönderirsiniz:

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

Meta başlığındaki csrf belirteci, yalnızca Blade tarafından oluşturulan bir _tokengiriş alanı olmadan bir form gönderirken kullanışlıdır .


1

Oturumunuzun sona ermesi durumunda, tekrar oturum açmak için bunu kullanabilirsiniz.

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

0

Aslında bu hatayı aldım ve bir çözüm bulamadım. Aslında bir ajax isteğinde bulunmadım. Bu sorunun sunucumdaki alt etki alanından mı kaynaklandığını bilmiyorum. İşte benim 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" );
                        }
                      }
                    });
                  });
                });

Bu yüzden aslında bir gönderi isteği yapmak yerine API'me gitmek için bir çapa ayarlıyorum, ki çoğu uygulamanın yaptığını anlıyorum.

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

0

Forma gizli bir CSRF (siteler arası istek sahteciliği) belirteç alanı eklemelisiniz, böylece CSRF koruması ara yazılımının isteği doğrulayabilmesi için .

Laravel, uygulama tarafından yönetilen her aktif kullanıcı oturumu için otomatik olarak bir CSRF "belirteci" oluşturur. Bu belirteç, kimliği doğrulanmış kullanıcının gerçekte uygulamaya isteklerde bulunan kişi olduğunu doğrulamak için kullanılır.

Bu nedenle, ajax isteklerini yaparken, csrf belirtecini data parametresi aracılığıyla iletmeniz gerekir . İşte örnek kod.

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

0

Formun içinde sadece @csrf kullanıyorum ve sorunsuz çalışıyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.