Laravel csrf-Token stimmt nicht mit der Ajax-POST-Anforderung überein

112

Ich versuche, Daten über Ajax aus der Datenbank zu löschen.

HTML:

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

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

Dies ist meine Abfrage zum Abrufen von Daten aus der Datenbank ...

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

Aber wenn ich auf Linkdaten löschen lösche nicht gelöscht und zeige csrf_token Mismatch ...

Ashish Singh
quelle
Sehen Sie sich diese: stackoverflow.com/questions/53684928/...
Prateek
Sie sollten Ihrem Ajax-Code Erfolg und Fehler hinzufügen. Der Fehler zeigt das Problem. stackoverflow.com/questions/45668337/…
reza jafari

Antworten:

175

Sie müssen Ihrer Ajax-Anfrage Daten hinzufügen . Ich hoffe es wird Arbeit.

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
Deepak Saini
quelle
32
Was ist, wenn sich die Ajax-Funktion in einer .jsDatei befindet?
Brane
1
Es funktioniert nicht auf Laravel 5.7. Zarpios Antwort ist richtig.
Omar Murcia
1
@Brane senden Sie den Token als Parameter in der Funktion
Abdelalim Hassouna
Dies funktioniert in Laravel 5.8 nicht. Es wird immer noch Token Mismatch angezeigt. Überprüfen Sie meine Antwort unten für eine einfache Lösung
Gjaa
Ändert Laravel das CSRF-Token nach einer JSON-Anfrage? Müssen Sie die neue an die Hauptseite senden?
Davefrassoni
182

Der beste Weg, um dieses Problem "X-CSRF-TOKEN" zu lösen, besteht darin, Ihrem Hauptlayout den folgenden Code hinzuzufügen und Ihre Ajax-Anrufe normal fortzusetzen:

Im Header

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

Im Skript

<script type="text/javascript">
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>
Zarpio
quelle
5
Danke, Mann. Dies ist eine abgerundete Lösung! Auf diese Weise richten Sie es nur einmal ein und schreiben anschließend Ihren normalen $ .ajax-Code.
pkid169
4
Dies ist die bessere Lösung, weil Sie es in .jsDateien verwenden können
Adam
3
Beste Antwort bisher. Vielen Dank.
Paul Denisevich
Was ist, wenn "global: false"?
Michel
Wie kann die CSRF nach jedem Aufruf aktualisiert werden? Der erste Aufruf funktioniert hervorragend. Nachfolgende Aufrufe schlagen aufgrund des CSRF-Tokens fehl.
Jjsg08
28

Ich denke, es ist besser, das Token in das Formular zu setzen und dieses Token per ID zu erhalten

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

Und die JQUery:

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

Auf diese Weise muss sich Ihr JS nicht in Ihren Blade-Dateien befinden.

cmnardi
quelle
25

Ich habe gerade headers:in Ajax Call hinzugefügt :

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

im Hinblick auf:

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

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

im Controller:

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

in route.php

Route::post('ajax', 'AjaxController@call');
lewis4u
quelle
1
Das Hinzufügen von Headern zum Ajax-Aufruf hat mir geholfen.
Chaudhry Waqas
1
Dies ist die beste Antwort, da JavaScript nicht in einer Blade-Datei enthalten sein muss (es sei denn, Sie möchten es in einer Blade-Datei, aber es wird jedes Mal gerendert, wenn jemand auf diese Seite kommt)
Zachary Weixelbaum
11

Wenn Sie Vorlagendateien verwenden, können Sie Ihr metaTag in den Kopf section(oder wie auch immer Sie es nennen) einfügen, der Ihre metaTags enthält.

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

Als nächstes müssen Sie das headersAttribut in Ihr Verzeichnis einfügen ajax(in meinem Beispiel verwende ich es datatablemit der serverseitigen Verarbeitung:

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

Hier ist das vollständige datatableAjax-Beispiel:

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

Danach sollten Sie 200 statusfür Ihre ajaxAnfrage erhalten.

Brane
quelle
6

Wissen Sie, dass es ein X-XSRF-TOKEN-Cookie gibt, das der Einfachheit halber gesetzt ist. Framework wie Angular und andere legen es standardmäßig fest. Überprüfen Sie dies im Dokument https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token. Möglicherweise möchten Sie es verwenden.

Der beste Weg ist, das Meta zu verwenden, falls die Cookies deaktiviert sind.

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

Hier der empfohlene Meta-Weg (Sie können das Feld beliebig platzieren, aber Meta ist ziemlich nett):

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

Beachten Sie die Verwendung von decodeURIComponent(), es wird aus dem Uri-Format dekodiert, das zum Speichern des Cookies verwendet wird. [Andernfalls erhalten Sie eine ungültige Nutzlastausnahme in Laravel].

Hier ist der Abschnitt über das CSRF-Cookie im Dokument zu überprüfen: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

Auch hier, wie Laravel (bootstrap.js) es standardmäßig für Axios einstellt:

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

Sie können überprüfen gehen resources/js/bootstrap.js.

Und hier lesen Sie die Cookie-Funktion:

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

Fügen Sie iddem metaElement, das das Token enthält, ein hinzu

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

Und dann können Sie es in Ihrem Javascript bekommen

$.ajax({
  url : "your_url",
  method:"post",
  data : {
    "_token": $('#csrf-token')[0].content  //pass the CSRF_TOKEN()
  },  
  ...
});
Gjaa
quelle
1
Wenn Sie keine ID hinzufügen möchten, verwenden Sie stattdessen einfach: $ ("[name = csrf-token]"). Attr ("content"). Das richtige Element wird anhand des Namensattributs abgerufen.
Pedro Sousa
3

Wenn Sie jQuery zum Senden von AJAX-Posts verwenden, fügen Sie diesen Code allen Ansichten hinzu:

$( 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 fügt allen Anfragen ein XSRF-Cookie hinzu, das wir automatisch an alle AJAX-Anfragen anhängen, bevor diese gesendet werden.

Sie können die getCookie-Funktion ersetzen, wenn eine andere Funktion oder ein anderes jQuery-Plugin vorhanden ist, um dasselbe zu tun.

AMIB
quelle
1

In Laravel 5.8 funktioniert das Festlegen des csrf-Meta-Tags für Ihr Layout und das Festlegen des Anforderungsheaders für csrf in den Ajax-Einstellungen nicht, wenn Sie mit ajax ein Formular senden, das bereits ein _tokenEingabefeld enthält, das bereits von der Laravel Blade-Template-Engine generiert wurde.

Sie müssen das bereits generierte csrf-Token aus dem Formular in Ihre Ajax-Anfrage aufnehmen, da der Server dies erwarten würde und nicht das in Ihrem Meta-Tag.

So _tokensieht beispielsweise das von Blade generierte Eingabefeld aus:

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

Anschließend senden Sie Ihr Formular mit Ajax wie folgt:

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

Das csrf-Token im Meta-Header ist nur nützlich, wenn Sie ein Formular ohne ein von Blade generiertes _tokenEingabefeld senden .

Udo E.
quelle
1

Wer immer ein Problem mit der akzeptierten Antwort @Deepak saini bekommt, versucht zu entfernen

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

für Ajax Anruf.

verwenden

dataType:"json",
Mrudul Addipalli
quelle
0

Ich hatte tatsächlich diesen Fehler und konnte keine Lösung finden. Am Ende habe ich keine Ajax-Anfrage gestellt. Ich weiß nicht, ob dieses Problem darauf zurückzuführen ist, dass es sich um eine Subdomain auf meinem Server handelt oder was. Hier ist meine Frage.

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

Also habe ich tatsächlich einen Anker eingerichtet, um zu meiner API zu gelangen, anstatt eine Post-Anfrage zu stellen, was meiner Meinung nach die meisten Anwendungen tun.

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

Sie sollten ein ausgeblendetes CSRF-Token-Feld (Cross Site Request Forgery) in das Formular aufnehmen, damit die CSRF-Schutz- Middleware die Anforderung validieren kann.

Laravel generiert automatisch ein CSRF- "Token" für jede aktive Benutzersitzung, die von der Anwendung verwaltet wird. Dieses Token wird verwendet, um zu überprüfen, ob der authentifizierte Benutzer tatsächlich die Anforderungen an die Anwendung stellt.

Wenn Sie Ajax- Anforderungen ausführen , müssen Sie das CSRF-Token über den Datenparameter übergeben. Hier ist der Beispielcode.

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

Ich benutze nur @csrf innerhalb des Formulars und es funktioniert gut

mich selber
quelle