it-swarm.com.de

Wie man CSRF-Token in einem AJAX Anfrage für ein Formular stellen?

Ich benutze Scala Play! 2.6 Framework, aber das ist möglicherweise nicht das Problem. Ich benutze ihr Javascript-Routing - und es scheint gut zu funktionieren, aber es hat Probleme. Ich habe ein Formular, das beim Rendern dies mit einem CSRF-Token erzeugt:

<form method="post" id="myForm" action="someURL">

<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>

Und hier ist ungefähr mein AJAX:

$(document).on('submit', '#myForm', function (event) {

 event.preventDefault();
   var data = {
    textvalue: $('#sometext').val()
   }
 var route = jsRoutes.controllers.DashboardController.postNewProject()
 $.ajax({
    url: route.url,
    type: route.type,
    data : JSON.stringify(data),
    contentType : 'application/json',
    success: function (data) { ...      },
    error: function (data) { ...  }
        })

});

Wenn ich dies poste, erhalte ich jedoch eine UNAUTHORIZED-Antwort von meinem Server, und meine Konsole in IntelliJ sagt mir, dass die CSRF-Prüfung fehlschlägt. Wie würde ich das CSRF-Token in der Anfrage weiterleiten?

9
NateH06

Ok, nachdem ich dies einige Stunden lang bekämpft und versucht hatte, Plays häufig fehlende Kontextdokumentation zum Thema zu entschlüsseln, habe ich es verstanden. 

Also aus ihren Unterlagen:

Um einen einfachen Schutz für Anfragen zu ermöglichen, die keine Browseranfragen sind, überprüft Play only Anfragen mit Cookies im Header. Wenn Sie Anfragen mit .__ machen. AJAX: Sie können das CSRF-Token in die HTML-Seite einfügen und es dann hinzufügen an die Anfrage mit dem Csrf-Token-Header.

Und dann gibt es keinen Code oder Beispiel. Danke spielen. Sehr beschreibend. Wie auch immer, hier ist wie:

in Ihrem view.html.formTemplate könnten Sie in IntelliJ schreiben:

@()
<form method="post" id="myForm" action="someURL">

@helper.CSRF.formField  <!-- This auto-generates a token for you -->
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>

Und dies wird bei der Auslieferung an den Kunden so dargestellt:

<form method="post" id="myForm" action="someURL">

<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>

Ok, fast da, jetzt müssen wir unseren AJAX - Aufruf erstellen. Ich habe alle meine in einer separaten main.js-Datei, aber Sie könnten dies auch in Ihren view.html.formTemplate eingeben, wenn Sie möchten.

$(document).on('submit', '#myForm', function (event) {

 event.preventDefault();
   var data = {
    myTextToPass: $('#sometext').val()
   }
 // LOOK AT ME! BETWEEN HERE AND
 var token =  $('input[name="csrfToken"]').attr('value')
    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader('Csrf-Token', token);
        }
    });
// HERE
 var route = jsRoutes.controllers.DashboardController.postNewProject()
 $.ajax({
    url: route.url,
    type: route.type,
    data : JSON.stringify(data),
    contentType : 'application/json',
    success: function (data) { ...      },
    error: function (data) { ...  }
        })

});

Mit dieser Zeile: var token = $('input[name="csrfToken"]').attr('value')Sie ziehen das in Ihrem Formularfeld automatisch generierte CSRF-Token aus und greifen dessen Wert in eine Variable, die in Ihrem Javascript verwendet wird. 

Der andere wichtige Teil von allem, was AJAX hier ist:

$.ajaxSetup({
            beforeSend: function(xhr) {
                xhr.setRequestHeader('Csrf-Token', token);
            }
        });

Mit dem $.ajaxSetup können Sie festlegen, was sich in der Kopfzeile befindet. Das müssen Sie aus ihrer Dokumentation entnehmen:

fügen Sie es der Anforderung mithilfe des Csrf-Token-Headers hinzu.

Viel Glück! Lass es mich wissen, wenn das klar ist. 


Note: Wenn Sie lusca verwenden, verwenden Sie X-CSRF-Token anstelle von Csrf-Token.

12
NateH06

fügen Sie es der Anforderung mithilfe der Csrf-Token-Kopfzeile hinzu.

Danke NateH06 für den Headernamen! Ich habe versucht, ein Csrf-Token für einen "Delete" -Button mit einem Ajax-Funktionsaufruf zu senden, und ich hielt Folgendes fest:

@import helper._
....
<button id="deleteBookBtn" class="btn btn-danger"
        data-csrf-name="@helper.CSRF.getToken.name"
        data-csrf-value="@helper.CSRF.getToken.value"
        data-delete-url="@routes.BooksController.destroy(book.id)"
        data-redirect-url="@routes.HomeController.index()">Delete</button>

Ich konnte keine Online-Js innerhalb des onclick() -Ereignisses hinzufügen, da ein CSP auf Spiel 2.6 gesetzt war.

Die Ausführung des Inline-Ereignishandlers wurde abgelehnt, weil er die folgende Richtlinie zur Richtlinie zur Inhaltssicherheit verletzt: "default-src 'self'".

Und in der JS-Datei:

function sendDeleteRequest(event) {
  url = event.target.getAttribute("data-delete-url")
  redirect = event.target.getAttribute("data-redirect-url")
  csrfTokenName = event.target.getAttribute("data-csrf-name")
  csrfTokenValue = event.target.getAttribute("data-csrf-value")
  $.ajax({
    url: url,
    method: "DELETE",
    beforeSend: function(request) {
      //'Csrf-Token' is the expected header name, not $csrfTokenName
      request.setRequestHeader(/*$csrfTokenName*/'Csrf-Token', csrfTokenValue);
    },
    success: function() {
      window.location = redirect;
    },
    error: function() {
      window.location.reload();
    }
  })
}

var deleteBookBtn = document.getElementById("deleteBookBtn");
if(deleteBookBtn) {
    deleteBookBtn.addEventListener("click", sendDeleteRequest);
}

Nachdem Sie den Headernamen als 'Csrf-Token' eingestellt haben, funktioniert der Ajax-Aufruf einwandfrei!

2
inieto

Von JSP 

<form method="post" id="myForm" action="someURL">
    <input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">    
</form>

Dies ist der einfachste Weg, der für mich funktioniert hat, nachdem ich um 3 Stunden gekämpft hatte. Holen Sie sich einfach das Token aus dem ausgeblendeten Eingabefeld und machen Sie während der Anforderung AJAX dieses Token wie folgt in den Header.

Von JQuery

var token =  $('input[name="csrfToken"]').attr('value'); 

Von einfachem Javascript

var token = document.getElementsByName("csrfToken").value;

Final AJAX Anfrage 

$.ajax({
      url: route.url,
      data : JSON.stringify(data),
      method : 'POST',
      headers: {
                    'X-CSRF-Token': token 
               },
      success: function (data) { ...      },
      error: function (data) { ...  }

});

Jetzt müssen Sie die Crsf-Sicherheit in der Web-Konfiguration nicht deaktivieren. Außerdem erhalten Sie auf der Konsole keinen 405-Fehler (Methode nicht zulässig).

Hoffe das hilft den Leuten .. !!

1
MOnkey

Für den Fall, dass es für andere von Nutzen ist, die herum googeln und versuchen zu verstehen, warum sie nicht das richtige Token anzeigen können ... Ich habe mit dem gleichen Problem für eine Play-Backend/React-Frontend-Kombination zu kämpfen - und daher nicht in der Lage, die Token-in-HTML-Seite-Technik (leicht) zu verwenden. Irgendwann stieß ich auf eine andere Lösung, um das aktuelle Token in einem Cookie festzulegen.

play.filters.csrf {
  cookie.name = "csrftoken"
}

an application.conf und das Cookie csrftoken wird auf das Token gesetzt. Ich habe dann https://www.npmjs.com/package/js-cookie verwendet, um den Wert in meinem JS-Code zu erfassen und ihn im Anforderungsheader zurückzusenden - ohne den Code hier, wie er ist = React nicht jQuery wie für das OP und will die Sache nicht verwechseln.

0
fredex42

Sie können Csrf-Token-Header mit der Option headers hinzufügen.

$.ajax({
    url: '@routes.MyController.myPostAction()',
    method: 'post',
    headers: {
        'Csrf-Token': '@play.filters.csrf.CSRF.getToken.map(_.value)'
    },
    data: {
        name: '@name'
    },
    success: function (data, textStatus, jqXHR) {
        location.reload();
    },
    error: function (jqXHR, textStatus, errorThrown) {
        debugger;
    }
});
0
Aha00a

Wie in der Dokumentation zu Play Framework 2.6 angegeben, können Sie einen "Csrf-Token" -Kopf mit dem von Play generierten Token setzen:

Wenn Sie Anforderungen mit AJAX stellen, können Sie das CSRF-Token auf der HTML-Seite platzieren und es dann mit dem Header Csrf-Token der Anforderung hinzufügen.

In einem Scala-Template können Sie den Token-Wert mit @helper.CSRF.getToken.value abrufen.

Nach der jQuerys-Dokumentation können Sie es entweder für alle Ajax-Anforderungen einmal festlegen, indem Sie jQuery mit ajaxSetup konfigurieren.

$.ajaxSetup({
  beforeSend: function(xhr) {
    xhr.setRequestHeader('Csrf-Token', '@helper.CSRF.getToken.value');
  }
});

oder setzen Sie alternativ den Header für jede Anforderung, indem Sie das headers-Objekt folgendermaßen konfigurieren:

$.ajax({
  url: route.url,
  ...
  headers: {
    'Csrf-Token': '@helper.CSRF.getToken.value'
  }
});
0
bmenzel