web-dev-qa-db-fra.com

Laravel csrf jeton mismatch pour ajax POST Demande

J'essaie de supprimer des données de la base de données 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

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

Ceci est ma requête pour récupérer les données de la base de données ...

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

Mais quand je clique sur Supprimer les données du lien non supprimées et que je montre l'incompatibilité de csrf_token ...

52
Ashish Singh

Vous devez ajouter data dans votre demande ajax. J'espère que ce sera un travail.

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
94
Deepak saini

La meilleure façon de résoudre ce problème "X-CSRF-TOKEN" consiste à ajouter le code suivant à votre mise en page principale et à passer vos appels ajax normalement:

Dans l'en-tête

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

En script

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

Je pense qu'il vaut mieux mettre le jeton dans le formulaire et obtenir ce jeton par identifiant

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

Et le JQUery: 

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

de cette façon, votre JS n'a pas besoin d'être dans vos fichiers de lame.

23
cmnardi

Je viens d'ajouter headers: dans l'appel ajax:

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

en vue:

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

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

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

dans le contrôleur:

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

dans routes.php

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

Si vous utilisez des fichiers de modèle, vous pouvez placer votre balise meta dans l'en-tête section (ou le nom de votre choix) contenant vos balises meta.

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

Ensuite, vous devez attribuer l'attribut headers à votre ajax (dans mon exemple, j'utilise datatable avec un traitement côté serveur:

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

Voici l'exemple complet datatable 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);
           }
        }
    });

Cela fait, vous devriez obtenir 200 status pour votre demande ajax.

9
raBne

si vous utilisez jQuery pour envoyer des publications AJAX, ajoutez ce code à toutes les vues:

$( 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 ajoute un cookie XSRF à toutes les demandes et nous l’ajoutons automatiquement à toutes les demandes AJAX juste avant la soumission.

Vous pouvez remplacer la fonction getCookie s'il existe une autre fonction ou un plugin jQuery permettant de faire la même chose.

2
AMIB

Ajouter un id à l'élément meta qui contient le jeton

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

Et puis vous pouvez l'obtenir dans votre Javascript

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

Pour Laravel 5.8, définir les balises méta csrf pour votre présentation et définir l'en-tête de demande pour csrf dans les paramètres ajax ne fonctionnera pas si vous utilisez ajax pour soumettre un formulaire qui inclut déjà un _token champ d’entrée généré par le moteur de templates de lames Laravel.

Vous devez inclure le jeton csrf déjà généré à partir du formulaire avec votre demande ajax car le serveur l'attendrait et non celui de votre balise méta.

Voici comment se présente le champ de saisie _token généré par Blade:

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

Vous soumettez ensuite votre formulaire avec ajax comme ceci:

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

Le jeton csrf dans l'en-tête de méta n'est utile que lorsque vous soumettez un formulaire sans champ de saisie _token généré par la lame.

0
Udo E.

Sachez qu'un cookie X-XSRF-TOKEN est configuré pour votre commodité. Un framework comme Angular et d'autres le définissent par défaut. Vérifiez ceci dans le doc https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token Vous voudrez peut-être l'utiliser.

Le meilleur moyen est d'utiliser la méta, si les cookies sont désactivés.

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

Voici le meta way recommandé (vous pouvez mettre le champ de toute façon, mais meta est tranquille, Nice):

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

Notez l'utilisation de decodeURIComponent(), il est décodé à partir du format uri utilisé pour stocker le cookie. [sinon vous obtiendrez une exception de charge utile invalide dans laravel].

Voici la section sur le cookie CSF dans la doc à vérifier: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

Ici aussi, comment laravel (bootstrap.js) le configure par défaut pour 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');
} 

vous pouvez aller vérifier resources/js/bootstrap.js.

Et ici, lisez la fonction 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;
    }
0
Mohamed Allal

En fait, j'ai eu cette erreur et je n'ai pas trouvé de solution. En fait, j'ai fini par ne pas faire de requête ajax. Je ne sais pas si ce problème était dû à la présence de ce sous-domaine sur mon serveur ou quoi. Voici ma requête.

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

J'ai donc créé une ancre pour accéder à mon API plutôt que de faire une demande de publication, ce que je suppose que la plupart des applications font.

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

Vous devez inclure un champ de jeton CSRF (falsification de requête intersite) masqué dans le formulaire afin que le CSRF protection middleware puisse valider la demande.

Laravel génère automatiquement un "jeton" CSRF pour chaque session d'utilisateur actif gérée par l'application. Ce jeton est utilisé pour vérifier que l'utilisateur authentifié est celui qui fait réellement les demandes à l'application.

Ainsi, lorsque vous effectuez des requêtes ajax, vous devez transmettre le jeton csrf via le paramètre data. Voici l'exemple de code.

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