Ich könnte über meinen AJAX-Beitrag Hilfe bei der Einhaltung des CSRF-Schutzmechanismus von Django gebrauchen. Ich habe die Anweisungen hier befolgt:
http://docs.djangoproject.com/de/dev/ref/contrib/csrf/
Ich habe den AJAX-Beispielcode, den sie auf dieser Seite haben, genau kopiert:
http://docs.djangoproject.com/de/dev/ref/contrib/csrf/#ajax
Ich habe eine Warnung eingefügt, die den Inhalt getCookie('csrftoken')
vor dem xhr.setRequestHeader
Anruf druckt, und er ist tatsächlich mit einigen Daten gefüllt. Ich bin nicht sicher, wie ich überprüfen soll, ob das Token korrekt ist, aber ich bin ermutigt, etwas zu finden und zu senden.
Aber Django lehnt meinen AJAX-Beitrag immer noch ab.
Hier ist mein JavaScript:
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
Hier ist der Fehler, den ich von Django sehe:
[23 / Feb / 2011 22:08:29] "POST / memorize / HTTP / 1.1" 403 2332
Ich bin mir sicher, dass mir etwas fehlt, und vielleicht ist es einfach, aber ich weiß nicht, was es ist. Ich habe mich in SO umgesehen und einige Informationen zum Deaktivieren der CSRF-Prüfung für meine Ansicht über das Internet angezeigtcsrf_exempt
Dekorateur gesehen, aber ich finde das unattraktiv. Ich habe das ausprobiert und es funktioniert, aber ich möchte lieber, dass mein POST so funktioniert, wie Django es erwartet, wenn möglich.
Nur für den Fall, dass es hilfreich ist, hier ist der Kern meiner Ansicht:
def myview(request):
profile = request.user.profile
if request.method == 'POST':
"""
Process the post...
"""
return HttpResponseRedirect('/memorize/')
else: # request.method == 'GET'
ajax = request.GET.has_key('ajax')
"""
Some irrelevent code...
"""
if ajax:
response = HttpResponse()
profile.get_stack_json(response)
return response
else:
"""
Get data to send along with the content of the page.
"""
return render_to_response('memorize/memorize.html',
""" My data """
context_instance=RequestContext(request))
Vielen Dank für Ihre Antworten!
Antworten:
Echte Lösung
Ok, ich habe es geschafft, das Problem aufzuspüren. Es liegt im Javascript-Code (wie ich unten vorgeschlagen habe).
Was Sie brauchen, ist Folgendes:
anstelle des Codes in den offiziellen Dokumenten: https://docs.djangoproject.com/de/2.2/ref/csrf/
Der Arbeitscode stammt aus diesem Django-Eintrag: http://www.djangoproject.com/weblog/2011/feb/08/security/
Die allgemeine Lösung lautet also: "Verwenden Sie den AjaxSetup-Handler anstelle des AjaxSend-Handlers." Ich weiß nicht warum es funktioniert. Aber es funktioniert bei mir :)
Vorheriger Beitrag (ohne Antwort)
Ich habe tatsächlich das gleiche Problem.
Es tritt nach dem Update auf Django 1.2.5 auf - es gab keine Fehler mit AJAX POST-Anforderungen in Django 1.2.4 (AJAX war in keiner Weise geschützt, aber es funktionierte einwandfrei).
Genau wie bei OP habe ich das in der Django-Dokumentation veröffentlichte JavaScript-Snippet ausprobiert. Ich verwende jQuery 1.5. Ich verwende auch die Middleware "django.middleware.csrf.CsrfViewMiddleware".
Ich habe versucht, dem Middleware-Code zu folgen, und ich weiß, dass dies fehlschlägt:
und dann
Dieses "wenn" ist wahr, weil "request_csrf_token" leer ist.
Grundsätzlich bedeutet dies, dass der Header NICHT gesetzt ist. Stimmt etwas mit dieser JS-Zeile nicht:
?
Ich hoffe, dass die angegebenen Details uns bei der Lösung des Problems helfen werden :)
quelle
ajaxSetup
anstatt zuajaxSend
laufen entgegen den jQuery-Dokumenten: api.jquery.com/jQuery.ajaxSetupWenn Sie die
$.ajax
Funktion verwenden, können Sie dascsrf
Token einfach in den Datenkörper einfügen:quelle
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
csrfmiddlewaretoken: '{{ csrf_token }}'
habe meindata
Wörterbuch in einem$.post
Anruf hinzugefügt .Fügen Sie diese Zeile Ihrem jQuery-Code hinzu:
und fertig.
quelle
CSRF Failed: CSRF token missing or incorrect.
Das Problem ist, dass Django erwartet, dass der Wert aus dem Cookie als Teil der Formulardaten zurückgegeben wird. Der Code aus der vorherigen Antwort erhält Javascript, um den Cookie-Wert zu ermitteln und in die Formulardaten einzufügen. Das ist eine schöne Art, es aus technischer Sicht zu tun, aber es sieht ein bisschen ausführlich aus.
In der Vergangenheit habe ich es einfacher gemacht, indem ich das Javascript dazu gebracht habe, den Token-Wert in die Post-Daten einzufügen.
Wenn Sie in Ihrer Vorlage {% csrf_token%} verwenden, wird ein ausgeblendetes Formularfeld ausgegeben, das den Wert enthält. Wenn Sie jedoch {{csrf_token}} verwenden, erhalten Sie nur den bloßen Wert des Tokens, sodass Sie diesen in Javascript wie diesem verwenden können.
Dann können Sie das mit dem erforderlichen Schlüsselnamen in den Hash aufnehmen, den Sie dann als Daten an den Ajax-Aufruf senden.
quelle
window
Objekt registrieren , damit Sie anschließend darauf zugreifen können . Auch in statischen Dateien.Die
{% csrf_token %}
darin enthaltenen HTML-Vorlagen<form></form>
übersetzt zu so etwas wie:
Warum grepst du es nicht einfach so in deinem JS:
und dann weitergeben, zB einen POST machen, wie:
quelle
Non-jquery Antwort:
Verwendung:
quelle
Wenn Ihr Formular in Django ohne JS korrekt veröffentlicht wird, sollten Sie es schrittweise mit Ajax erweitern können, ohne dass das CSRF-Token gehackt oder unordentlich weitergegeben wird. Serialisieren Sie einfach das gesamte Formular und das wird automatisch alle Ihre Formularfelder einschließlich des versteckten csrf-Felds aufnehmen:
Ich habe dies mit Django 1.3+ und jQuery 1.5+ getestet. Dies funktioniert natürlich für jedes HTML-Formular, nicht nur für Django-Apps.
quelle
Verwenden Sie Firefox mit Firebug. Öffnen Sie die Registerkarte "Konsole", während Sie die Ajax-Anforderung auslösen. Mit erhalten
DEBUG=True
Sie die nette Django-Fehlerseite als Antwort und Sie können sogar das gerenderte HTML der Ajax-Antwort auf der Registerkarte Konsole sehen.Dann wissen Sie, was der Fehler ist.
quelle
Die akzeptierte Antwort ist höchstwahrscheinlich ein roter Hering. Der Unterschied zwischen Django 1.2.4 und 1.2.5 bestand in der Anforderung eines CSRF-Tokens für AJAX-Anforderungen.
Ich bin auf dieses Problem bei Django 1.3 gestoßen und es wurde dadurch verursacht, dass das CSRF-Cookie überhaupt nicht gesetzt wurde. Django setzt den Cookie nur, wenn dies erforderlich ist. Eine ausschließlich oder stark ajax-Site, die unter Django 1.2.4 ausgeführt wird, hätte möglicherweise niemals ein Token an den Client gesendet, und das Upgrade, für das das Token erforderlich ist, würde die 403-Fehler verursachen.
Die ideale Lösung finden Sie hier: http://docs.djangoproject.com/de/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form,
aber Sie müssten auf 1.4 warten, es sei denn Dies ist nur eine Dokumentation, die den Code einholt
Bearbeiten
Beachten Sie auch, dass die späteren Django-Dokumente einen Fehler in jQuery 1.5 feststellen. Stellen Sie daher sicher, dass Sie 1.5.1 oder höher mit dem von Django vorgeschlagenen Code verwenden: http://docs.djangoproject.com/de/1.3/ref/contrib/csrf/# Ajax
quelle
ensure_csrf_cookie
, mit dem Sie eine Ansicht umschließen können, um sicherzustellen, dass der Cookie gesendet wird.csrftoken
Cookie, danke!Es scheint, dass niemand erwähnt hat, wie dies in reinem JS mithilfe des
X-CSRFToken
Headers gemacht werden{{ csrf_token }}
soll. Hier ist eine einfache Lösung, bei der Sie weder die Cookies noch das DOM durchsuchen müssen:quelle
Da dies in den aktuellen Antworten nirgends angegeben ist, ist die schnellste Lösung, wenn Sie js nicht in Ihre Vorlage einbetten, folgende:
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
Fügen Sie vor Ihren Verweis auf die Datei script.js in Ihre Vorlage ein und fügencsrfmiddlewaretoken
Sie sie dann in Ihrdata
Wörterbuch in Ihrer js-Datei ein:quelle
Ich habe gerade eine etwas andere, aber ähnliche Situation erlebt. Ich bin mir nicht 100% sicher, ob es sich um eine Lösung für Ihren Fall handelt, aber ich habe das Problem für Django 1.3 behoben, indem ich einen POST-Parameter 'csrfmiddlewaretoken' mit der richtigen Cookie-Wertzeichenfolge festgelegt habe, die normalerweise von Django in Form Ihres Home-HTML zurückgegeben wird Vorlagensystem mit dem Tag '{% csrf_token%}'. Ich habe den älteren Django nicht anprobiert, bin einfach passiert und habe mich für Django1.3 entschieden. Mein Problem war, dass die erste Anfrage, die über Ajax von einem Formular gesendet wurde, erfolgreich ausgeführt wurde, aber der zweite Versuch von genau demselben fehlgeschlagen führte, führte zu einem 403-Status, obwohl der Header 'X-CSRFToken' auch korrekt mit dem CSRF-Token-Wert platziert wurde wie im Fall des ersten Versuchs. Hoffe das hilft.
Grüße,
Hiro
quelle
Sie können dieses js in Ihre HTML-Datei einfügen. Denken Sie daran, es vor andere js-Funktionen zu stellen
quelle
Jeder Sitzung wird ein CSRF-Token zugewiesen (dh jedes Mal, wenn Sie sich anmelden). Bevor Sie also Daten vom Benutzer eingeben lassen und diese als Ajax-Aufruf an eine Funktion senden möchten, die durch csrf_protect decorator geschützt ist, versuchen Sie, die Funktionen zu finden, die aufgerufen werden, bevor Sie diese Daten vom Benutzer erhalten. Beispielsweise muss eine Vorlage gerendert werden, für die Ihr Benutzer Daten eingibt. Diese Vorlage wird von einer Funktion gerendert. In dieser Funktion können Sie das csrf-Token wie folgt abrufen: csrf = request.COOKIES ['csrftoken'] Übergeben Sie nun diesen csrf-Wert im Kontextwörterbuch, für das die betreffende Vorlage gerendert wird. Schreiben Sie nun in diese Vorlage diese Zeile: Schreiben Sie nun in Ihrer Javascript-Funktion, bevor Sie eine Ajax-Anfrage stellen, Folgendes: var csrf = $ ('# csrf'). val () wählt den Wert des an die Vorlage übergebenen Tokens aus und speichert ihn in der Variablen csrf. Übergeben Sie jetzt beim Ajax-Aufruf in Ihren Post-Daten auch diesen Wert: "csrfmiddlewaretoken": csrf
Dies funktioniert auch dann, wenn Sie keine Django-Formulare implementieren.
Tatsächlich lautet die Logik hier: Sie benötigen ein Token, das Sie auf Anfrage erhalten können. Sie müssen also nur herausfinden, welche Funktion unmittelbar nach der Anmeldung aufgerufen wird. Wenn Sie dieses Token haben, führen Sie entweder einen weiteren Ajax-Aufruf durch, um es abzurufen, oder übergeben Sie es an eine Vorlage, auf die Ihr Ajax zugreifen kann.
quelle
csrftoken: csrftoken
anstattcsrfmiddlwaretoken: csrftoken
. Nach der Änderung hat es funktioniert. Dankefür jemanden, der darauf stößt und versucht zu debuggen:
1) Der Django-CSRF-Check (vorausgesetzt, Sie senden einen) ist hier
2) In meinem Fall
settings.CSRF_HEADER_NAME
wurde "HTTP_X_CSRFTOKEN" gesetzt und mein AJAX-Aufruf sendete einen Header mit dem Namen "HTTP_X_CSRF_TOKEN", sodass nichts funktionierte. Ich könnte es entweder im AJAX-Aufruf oder in der Django-Einstellung ändern.3) Wenn Sie sich dafür entscheiden, es serverseitig zu ändern, suchen Sie Ihren Installationsort für django und setzen Sie einen Haltepunkt in die von
csrf middleware
Ihnen verwendete .f. Dies ist ungefährvirtualenv
so:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
Stellen Sie dann sicher, dass die
csrf
Stellen Sie Token korrekt aus request.META bezogen wurde4) Wenn Sie Ihren Header usw. ändern müssen, ändern Sie diese Variable in Ihrer Einstellungsdatei
quelle
Wenn jemand mit Axios kämpft, um diese Arbeit zu machen, hat mir das geholfen:
Quelle: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/
quelle
In meinem Fall lag das Problem bei der Nginx-Konfiguration, die ich vom Hauptserver auf einen temporären Server kopiert habe, wobei https deaktiviert wurde, das auf dem zweiten Server nicht benötigt wird.
Ich musste diese beiden Zeilen in der Konfiguration auskommentieren, damit es wieder funktioniert:
quelle
Hier ist eine weniger ausführliche Lösung von Django:
Quelle: https://docs.djangoproject.com/de/1.11/ref/csrf/
quelle