it-swarm.com.de

"CSRF-Token fehlt oder ist falsch" beim Nachlaufparameter über AJAX in Django

Ich versuche Parameter zu posten 

 jQuery.ajax(
        {
            'type': 'POST',
            'url': url,
            'contentType': 'application/json',
            'data': "{content:'xxx'}",
            'dataType': 'json',
            'success': rateReviewResult 
        }
    );

Django gibt jedoch Forbidden 403. CSRF verification failed. Request aborted..__ zurück. Ich verwende 'Django.middleware.csrf.CsrfViewMiddleware' und konnte nicht finden, wie ich dieses Problem verhindern kann, ohne die Sicherheit zu beeinträchtigen.

52
brsbilgic

Sie können AJAX auf zwei verschiedene Arten einen Post-Request stellen:

  1. Um Ihrer Ansicht mitzuteilen, das CSRF-Token nicht zu überprüfen. Dies kann mit dem Dekorator @csrf_exempt wie folgt durchgeführt werden:

    from Django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def your_view_name(request):
        ...
    
  2. Um ein CSRF-Token in jede Anforderung von AJAX einzubetten, kann es für jQuery Folgendes sein:

    $(function () {
        $.ajaxSetup({
            headers: { "X-CSRFToken": getCookie("csrftoken") }
        });
    });
    

    Wo die getCookie-Funktion das csrf-Token von Cookies abruft. Ich verwende die folgende Implementierung:

    function getCookie(c_name)
    {
        if (document.cookie.length > 0)
        {
            c_start = document.cookie.indexOf(c_name + "=");
            if (c_start != -1)
            {
                c_start = c_start + c_name.length + 1;
                c_end = document.cookie.indexOf(";", c_start);
                if (c_end == -1) c_end = document.cookie.length;
                return unescape(document.cookie.substring(c_start,c_end));
            }
        }
        return "";
     }
    

    Außerdem hat jQuery ein Plugin für den Zugriff auf Cookies.

    // set cookie
    $.cookie('cookiename', 'cookievalue');<br>
    // read cookie
    var myCookie = $.cookie('cookiename');<br>
    // delete cookie
    $.cookie('cookiename', null);
    
81
sigurd

Der einfachste Weg, den ich gefunden habe, besteht darin, den {{csrf_token}}-Wert in die Daten aufzunehmen:

jQuery.ajax(
    {
        'type': 'POST',
        'url': url,
        'contentType': 'application/json',
        'data': {
            'content': 'xxx',
            'csrfmiddlewaretoken': '{{ csrf_token }}',
        },
        'dataType': 'json',
        'success': rateReviewResult 
    }
);
34
jerrykan

Ich habe eine Weile gebraucht, um zu verstehen, was ich mit dem Code tun sollte, das Daniel gepostet hat. Aber eigentlich müssen Sie es nur am Anfang der Javascript-Datei einfügen. 

Für mich ist die beste Lösung bisher:

  1. Erstellen Sie eine csrf.js-Datei

  2. Fügen Sie den Code in die csrf.js-Datei ein

  3. Verweisen Sie auf den Code in der Vorlage, die Sie benötigen

    <script type="text/javascript" src="{{ STATIC_PREFIX }}js/csrf.js"></script>
    

Beachten Sie, dass STATIC_PREFIX/js/csrf.js auf meine Datei verweist. Ich lade die Variable STATIC_PREFIX tatsächlich mit {% get_static_prefix as STATIC_PREFIX %}.


Erweiterter Tipp: Wenn Sie Vorlagen verwenden und etwas wie base.html haben, von dem aus Sie erweitern, können Sie das Skript von dort aus referenzieren und Sie müssen sich keine Sorgen mehr um den Rest Ihrer Dateien machen. Soweit ich weiß, sollte dies auch keine Sicherheitslücke darstellen.

23
toto_tico

Einfach und kurz

$.ajaxSetup({
  headers: { "X-CSRFToken": '{{csrf_token}}' }
});

OR

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
  beforeSend: function(xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", '{{csrf_token}}');
    }
  }
});

docs

8
Khaino

Ich habe gestern das gleiche Problem bekommen und dachte, es würde den Leuten helfen, wenn es einen einfachen Weg geben würde, also schrieb ich ein jQuery-Plugin dafür: jquery.djangocsrf . Anstatt das CSRF-Token in jeder Anforderung hinzuzufügen, bindet es sich selbst an das AjaxSend-Ereignis jQuery und fügt das Client-Cookie in einem Header hinzu.

So verwenden Sie es:

1- schließen Sie es ein:

<script src="path/to/jquery.js"></script>
<script src="path/to/jquery.cookie.js"></script>
<script src="path/to/jquery.djangocsrf.js"></script>

2- aktivieren Sie es in Ihrem Code:

$.djangocsrf( "enable" );

Django fügt das Token immer in ein Cookie ein, wenn Ihre Vorlage {% csrf_token %} verwendet. Um sicherzustellen, dass es immer hinzugefügt wird, auch wenn Sie das spezielle Tag in Ihrer Vorlage nicht verwenden, verwenden Sie den Dekorator @ensure_csrf_cookie:

from Django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def my_view(request):
    return render(request, 'mytemplate.html')

Hinweis: Ich verwende Django 1.6.2.

4
bfontaine

Vielen Dank an alle für alle Antworten. Ich benutze Django 1.5.1. Ich bin ein bisschen spät auf der Party, aber hier geht es.

Ich fand den Link zum Django-Projekt sehr nützlich, aber ich wollte nicht unbedingt den zusätzlichen JavaScript-Code einbinden, wenn ich einen Ajax-Aufruf machen wollte.

Ich mag jerrykans Antwort, da sie sehr knapp ist und nur eine Zeile zu einem ansonsten normalen Ajax-Anruf hinzufügt. Als Antwort auf die Kommentare unter seinem Kommentar zu Situationen, in denen Django-Vorlagen-Tags nicht verfügbar sind, wie wäre es mit dem Laden der csrfmiddlewaretoken aus dem DOM?

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    data: { 'csrfmiddlewaretoken': token },
    dataType: 'json',
    success: function(data) { console.log('Yippee! ' + data); } 
});

EDIT März 2016

Meine Einstellung zu diesem Thema hat sich in den letzten Jahren geändert. Ich füge den folgenden Code (von Django docs ) zu einer main.js-Datei hinzu und lade ihn auf jeder Seite. Wenn Sie fertig sind, müssen Sie sich nicht mehr um den CSRF-Token mit ajax kümmern.

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

4
jbiz

x-csrftoken-Header in die Anfrage einschließen:

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    beforeSend : function(jqXHR, settings) {
        jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie());
    },
    data: data,
    dataType: 'json',

});
3
Hasan Ramezani

Da es keine direkte Antwort gibt, müssen Sie lediglich den Header X-CSRFToken zur ajax-Anforderung hinzufügen, die sich im Cookie csrftoken befindet. JQuery verwendet keine Cookies (aus irgendeinem Grund) ohne ein Plugin so:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

und die minimale Codeänderung ist:

$.ajax({
  headers: { "X-CSRFToken": $.cookie("csrftoken") },
  ...
});
3
CpILL

Die schnellste Lösung ohne Plugins, wenn Sie keine js in Ihre Vorlage einbetten, ist: 

Fügen Sie <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script> vor Ihrem Verweis auf die Datei script.js in Ihre Vorlage ein und fügen Sie dann csrfmiddlewaretoken in Ihr data-Wörterbuch ein:

$.ajax({
            type: 'POST',
            url: somepathname + "do_it/",
            data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
            success: function() {
                console.log("Success!");
            }
        })

Wenn Sie Ihre Js in die Vorlage einbetten, ist es so einfach: data: {csrfmiddlewaretoken: '{{ csrf_token }}'}

1
Marek Židek

Wenn jemand nach dem Lesen anderer Antworten immer noch Probleme hat, versuchen Sie Folgendes:

   $.ajax({
            type: "POST",
            beforeSend: function (request)
            {
                request.setRequestHeader("X-CSRF-TOKEN", "${_csrf.token}");
            },
            url: servlet_path,
            data : data,
            success : function(result) {
            console.log("Success!");
   }
});
0
Fr333du