wake-up-neo.net

403 Verbotener Fehler beim Erstellen einer Ajax-Post-Anfrage im Django-Framework

Ich versuche, Jquery in eine Webanwendung zu integrieren, die ich mit Django Framework mache. Es fällt mir jedoch schwer, einen einfachen Aufruf von ajax zur Arbeit zu machen. Meine Vorlagendatei, die das Formular html und javascript enthält, um den Ajax-Aufruf abzuwickeln, sieht folgendermaßen aus:

<script type="text/javascript">
$(document).ready(function() {
$( "#target" ).submit(function() {
console.log('Form was submitted');
$.ajax({
        type: "POST",
        url: "/hello/",  // or just url: "/my-url/path/"
        data: {
            query: $( "#query" ).val()   
        },
        success: function(data) {
            console.log(data);
        }
    });
return false;
  });   
  })
</script>
<form id="target" action="." method="post">{% csrf_token %}
 <input id= "query" type="text" value="Hello there">
 <input type="submit" value="Search Recent Tweets">
</form>

Mein views.py, der den Ajax-Aufruf behandeln soll, sieht folgendermaßen aus:

 from Django.core.context_processors import csrf
 from Django.shortcuts import render_to_response
 from Django.template.loader import get_template
 from Django.template import Context,RequestContext
 from Django.views.decorators.csrf import ensure_csrf_cookie
 from Django.http import HttpResponse

 # access resource
 def hello(request):
  c = {}
  c.update(csrf(request))
  if request.is_ajax():
        t = get_template('template.html')
        #html = t.render(Context({'result': 'hello world'}))
        con = RequestContext(request, {'result': 'hello world'})
        return render_to_response('template.html', c, con)
  else:
        return HttpResponse('Not working!') 

Ich habe versucht, der offiziellen Dokumentation zu Cross-Site Request Forgery Protection zu folgen, und habe mir auch mehrere Stackoverflow-Fragen angesehen, die ein ähnliches Problem ansprechen. Ich habe den {% csrf_token %} in meine html-Vorlagendatei aufgenommen, aber es scheint immer noch nicht zu funktionieren. In der Konsole wird eine Fehlermeldung angezeigt, die darauf hinweist, dass der Ajax-Aufruf fehlgeschlagen ist:

POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN)   

Wie übergebe ich die Variable result zusammen mit meiner http-Antwort und den ajax-Aufruf zum reibungslosen Funktionieren bringen? Jede Hilfe wird sehr geschätzt.

Edit-1

Ich habe angeblich nicht das csrf-Token zusammen mit meiner Post-Anfrage übergeben. SO Wie in der Dokumentation angegeben, fügte ich meinem Template-Javascript den folgenden Code hinzu:

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');
console.log(csrftoken);

//Ajax call
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    crossDomain: false, // obviates need for sameOrigin test
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type)) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

Wenn ich die HTML-Vorlagenseite im Browser aktualisiere, erhalte ich in der Konsole null, was darauf hindeutet, dass das Cookie nicht gesetzt oder definiert ist. Was vermisse ich?

30
Annihilator8080

Da Sie das csrfmiddlewaretoken nicht gepostet haben, verbietet Django Ihnen das ... _. dieses Dokument kann Ihnen helfen.

40
Yohn

Für die faulen Jungs:

Laden Sie zuerst den Cookie herunter: http://plugins.jquery.com/cookie/

Fügen Sie es Ihrer HTML-Datei hinzu:

<script src="{% static 'designer/js/jquery.cookie.js' %}"></script>

Jetzt können Sie eine funktionierende POST - Anforderung erstellen:

var csrftoken = $.cookie('csrftoken');

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", csrftoken);
        }
    }
});

$.ajax(save_url, {
    type : 'POST',
    contentType : 'application/json',
    data : JSON.stringify(canvas),
    success: function () {
        alert("Saved!");
    }

})
21
fivef

Ich finde alle vorherigen Antworten vor Ort, aber stellen wir die Dinge in einen Kontext.

Die 403-verbotene Antwort stammt von der CSRF-Middleware (siehe Cross Site Request Forgery-Schutz ): 

Standardmäßig wird dem Benutzer eine Antwort "403 Forbidden" gesendet, wenn eine eingehende Anforderung die von CsrfViewMiddleware durchgeführten Prüfungen nicht besteht.

Viele Optionen stehen zur Verfügung. Ich würde empfehlen, der Antwort von @fivef zu folgen, damit jQuery vor jeder AJAX - Anforderung mit X-CSRFToken den $.ajaxSetup-Header hinzufügt.

Diese Antwort erfordert das Cookie-Plugin jQuery. Wenn dies nicht erwünscht ist, besteht die Möglichkeit, Folgendes hinzuzufügen:

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

ABER: Wenn die Einstellung CSRF_COOKIE_HTTPONLY auf True gesetzt ist, was oft als Security-Middleware empfohlen wird, ist der Cookie nicht vorhanden, selbst wenn @ensure_csrf_cookie() verwendet wird. In diesem Fall muss {% csrf_token %} in jedem Formular angegeben werden, das eine Ausgabe wie <input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden"> erzeugt. Die Variable csrfToken würde also einfach erhalten mit:

var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();

Natürlich wäre wieder $.ajaxSetup erforderlich.

Andere Optionen, die verfügbar sind, aber nicht empfohlen sind, die Middleware oder den csrf-Schutz für das spezifische Formular mit @csrf_exempt() zu deaktivieren.

5
Wtower

Verwenden Sie zum Festlegen des Cookies den Dekorator ensure_csrf_cookie in Ihrer Ansicht:

from Django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def hello(request):
    code_here()
2
kelvinss

Stellen Sie sicher, dass Sie die Seite/Ansicht nicht zwischenspeichern, auf der Ihr Formular angezeigt wird. Es könnte sein, dass Sie Ihren CSRF_TOKEN zwischenspeichern. Passierte mir!

1
teewuane
data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}

Sie sehen "403 (FORBIDDEN)", weil Sie den Parameter "csrfmiddlewaretoken" nicht senden. In der Vorlage hat jedes Formular Folgendes: {% csrf_token%}. Sie sollten "csrfmiddlewaretoken" zu Ihrem Ajax-Datenwörterbuch hinzufügen. Mein Beispiel sendet "product_code" und "csrfmiddlewaretoken" an die App "basket" view "remove":

$(function(){
    $('.card-body').on('click',function(){
        $.ajax({
          type: "post",
          url: "{% url 'basket:remove'%}",
          data: {"product_code": "07316", "csrfmiddlewaretoken" : "{{csrf_token}}" }
        });
    })
});
1
AndrewPt

Die schnellste Lösung, wenn Sie js nicht 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

Versuchen Sie, diesen Dekorator in Ihren Versandcode aufzunehmen

from Django.utils.decorators import method_decorator
from Django.views.decorators.csrf import csrf_exempt     
@method_decorator(csrf_exempt, name='dispatch')
def dispatch(self, request, *args, **kwargs):
     return super(LessonUploadWorkView,self).dispatch(request,*args,**kwargs)
1
mullerivan

Mit SSL/https und mit CSRF_COOKIE_HTTPONLY = False habe ich immer noch kein csrftoken im Cookie, entweder mit der Funktion getCookie (name), die in Django Doc oder der jquery) vorgeschlagen wird. cookie.js vorgeschlagen von fivef .

Wtower Die Zusammenfassung ist perfekt und ich dachte, es würde funktionieren, nachdem ich CSRF_COOKIE_HTTPONLY aus den settings.py entfernt habe, aber nicht in https!

Warum ist csrftoken in document.cookie nicht sichtbar ???

Anstatt zu bekommen 

"Django_language = fr; csrftoken = rDrGI5cp98MnooPIsygWIF76vuYTkDIt"

Ich bekomme nur

"Django_language = fr"

WARUM? Wie SSL/https entfernt X-CSRFToken aus den Kopfzeilen Ich dachte, es lag an den Proxy-Header-Params von Nginx, aber anscheinend nicht ... Irgendeine Idee?

Im Gegensatz zu Django doc Notes scheint es nicht möglich zu sein, mit csrf_token in Cookies mit https zu arbeiten. Die einzige Möglichkeit, csrftoken zu übergeben, besteht im DOM, indem Sie {% csrf_token%} in html verwenden und es in jQuery mithilfe von erhalten

var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();

Es ist dann möglich, es an ajax entweder über einen Header ( xhr.setRequestHeader ) oder über params zu übergeben.

0
openHBP