Django CSRF Cookie nicht gesetzt

85

Ich habe seit einiger Zeit ein Problem. Ich habe festgestellt, dass das CSRF-Cookie nicht gesetzt ist. Bitte beachten Sie die Codes unten

Python

def deposit(request,account_num):
if request.method == 'POST':
    account = get_object_or_404(account_info,acct_number=account_num)
    form_=AccountForm(request.POST or None, instance=account)
    form = BalanceForm(request.POST)
    info = str(account_info.objects.filter(acct_number=account_num))
    inf=info.split()
    if form.is_valid():
    #cd=form.cleaned_data
        now = datetime.datetime.now()
        cmodel = form.save()
        cmodel.acct_number=account_num
        #RepresentsInt(cmodel.acct_number)
        cmodel.bal_change="%0.2f" % float(cmodel.bal_change)
        cmodel.total_balance="%0.2f" %(float(inf[1]) + float(cmodel.bal_change))
        account.balance="%0.2f" % float(cmodel.total_balance)
        cmodel.total_balance="%0.2f" % float(cmodel.total_balance)
        #cmodel.bal_change=cmodel.bal_change
        cmodel.issued=now.strftime("%m/%d/%y %I:%M:%S %p")
        account.recent_change=cmodel.issued
        cmodel.save()
        account.save()
        return HttpResponseRedirect("/history/" + account_num + "/")
    else:
        return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))

Im HTML ist hier der Code

HTML

<form action="/deposit/{{ account_num }}/" method="post">

<table>
<tr>
{{ account_form.bal_change }}
&nbsp;
<input type="submit" value="Deposit" />
</tr>
{% csrf_token %}
</table>
</form>

Ich stecke fest, ich habe das Cookie bereits gelöscht, einen anderen Browser verwendet, aber immer noch kein CSRF-Cookie gesetzt.


quelle
Hast du CsrfViewMiddlewarein deiner MIDDLEWARE_CLASSESEinstellung?
Alecxe
Fügen Sie {%csrf_token%}in Ihrem Formular die Vorlage hinzu.
Rohan
4
@Rohan es ist schon da, siehe die Frage.
Alecxe
1
Ja, ich habe bereits CsrfViewMiddleware und ich habe bereits das csrf_token in meinem Formular
Ich habe das Django-Cors-Modul verwendet und über ReactJS darauf zugegriffen. (Beide waren auf localhost). Ich hatte auch dieses Problem des OP. Ich fand für mich, dass das Hinzufügen credentials: 'include'zur POST-Anfrage und dann AUCH das Hinzufügen in djangos settings.py: CORS_ALLOW_CREDENTIALS = Truedas Problem behoben zu haben scheint, ohne dass das Hinzufügen @csrf_exemptzur Ansicht erforderlich ist . Es ist tatsächlich in den Dokumenten ... pypi.org/project/django-cors-headers-multi * Ich weiß, dass dies mit einer der obigen Fragen zusammenhängt, aber ich kann noch keinen Kommentar abgeben und wollte hoffentlich jemand anderem die Zeit dafür sparen nahm mich, um t
DW

Antworten:

132

Dies kann auch auftreten, wenn festgelegt CSRF_COOKIE_SECURE = Trueist und Sie nicht sicher auf die Site zugreifen oder wenn dies CSRF_COOKIE_HTTPONLY = Truewie hier und hier angegeben festgelegt ist

Druska
quelle
10
Vielen Dank! Gleiches gilt für SESSION_COOKIE_SECURE = True.
NonameSL
75
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def your_view(request):
    if request.method == "POST":
        # do something
    return HttpResponse("Your response")
Евгений Смирнов
quelle
59
Das vollständige Deaktivieren des Sicherheitsmechanismus ist keine gute Möglichkeit, den Fehler zu beheben.
Guillaume Algis
2
Wenn Sie 2017 Cookiecutter-Django verwenden, ist dies die richtige Antwort in der Produktion.
André Duarte
1
Warum ist das aus Neugier?
Patrick Gallagher
3
Diese Antwort schlägt nicht vor, "den Sicherheitsmechanismus vollständig zu deaktivieren", sondern zeigt nur, wie dies in einem Einzelfall zu tun ist, in dem Sie das CSRF-Token möglicherweise nicht verwenden können. Dies ist mein Fall, in dem ich einem externen Client eine POST-Aktion anbieten muss.
Mariotomo
Dies ist eine TODO-Art von Element, das ich während der Entwicklungsphase verwende, wenn Sie kein CSRF-Token über die Benutzeroberfläche bereitstellen können. Aber sicherlich nicht für eine Live-App zu empfehlen.
Aman Madan
24

Wenn Sie die HTML5-Abruf-API verwenden , um POST-Anforderungen als angemeldeter Benutzer zu stellen und abzurufen Forbidden (CSRF cookie not set.), kann dies daran liegen, dass standardmäßig fetchkeine Sitzungscookies enthalten sind, was dazu führt, dass Django denkt, Sie seien ein anderer Benutzer als derjenige, der die Seite geladen hat .

Sie können das Sitzungstoken einschließen, indem Sie die Option credentials: 'include'zum Abrufen übergeben:

var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
    method: 'POST',
    body: payload,
    headers: headers,
    credentials: 'include'
})
user85461
quelle
Darf ich wissen, welche Header () -Methode Sie instanziiert haben? ist das globale Javascript-Methode?
Abz Rockers
@AbzRockers: Ja, Headersist eine globale Javascript-Schnittstelle, die Teil der HTML5-Abruf-API ist. developer.mozilla.org/en-US/docs/Web/API/Headers
user85461
12

Von diesem können Sie es , indem Sie den lösen ensure_csrf_cookie Dekorateur zu Ihrer Ansicht

from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
 #...

wenn diese Methode nicht funktioniert. Sie werden versuchen, csrf in Middleware zu kommentieren. und erneut testen.

dscanon
quelle
4

Bei der Arbeit mit DRF stieß ich auf eine ähnliche Situation. Die Lösung bestand darin, die Methode .as_view () an die Ansicht in urls.py anzuhängen

Pratik Mhatre
quelle
Es wäre besser, wenn Sie auch Code einfügen würden
Alex Jolig
1
@AlexJolig hatte nur das gleiche Problem. Das Problem war, dass ich vergessen hatte, nach .as_view()meinem ApiView etwas hinzuzufügen. So sah Code aus: urlpatterns += path('resource', ResourceView)Und so sollte es aussehen: urlpatterns += path('resource', ResourceView.as_view())
Alveona
4

Wenn Sie DRF verwenden, überprüfen Sie, ob Ihre URL-Muster korrekt sind. Vielleicht haben Sie vergessen .as_view():

So sah mein Code aus:

urlpatterns += path('resource', ResourceView) 

Und so sollte es sein:

urlpatterns += path('resource', ResourceView.as_view())
Alveona
quelle
1

Versuchen Sie zu überprüfen, ob Sie in der settings.py installiert haben

 MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)

In der Vorlage werden die Daten mit dem csrf_token formatiert:

<form>{% csrf_token %}
</form>
drabo2005
quelle
Ich habe nicht Ihren gesamten Code, aber ich glaube, dass die Angelegenheit hier ist: def Einzahlung (Anfrage, account_num): geändert in def Einzahlung (Anfrage): und einen Weg finden, die account_num zurückzurufen. Jetzt hängt es davon ab, ob account_num ein Tabellenfeld oder eine Variable ist.
drabo2005
Es ist eine Variable {{account_num}}, aber wie wirkt sich das auf das csrf-Token aus?
Ich glaube, dass sich das CSRF-Token nur auf die Anfrage bezog, daher kann es nicht überprüfen oder verarbeiten, was hier mit der Variablen geschieht. Überprüfen Sie auf djangoproject.com, ob Sie möglicherweise eine richtige Antwort auf das csrf_token erhalten.
drabo2005
1

Dieses Problem trat kürzlich aufgrund eines Fehlers in Python selbst erneut auf.

http://bugs.python.org/issue22931

https://code.djangoproject.com/ticket/24280

Unter den betroffenen Versionen waren 2.7.8 und 2.7.9. Das Cookie wurde nicht richtig gelesen, wenn einer der Werte ein [Zeichen enthielt .

Das Aktualisieren von Python (2.7.10) behebt das Problem.

sbaechler
quelle
1

Dies tritt auch auf, wenn Sie die Formularaktion nicht festlegen.
Für mich zeigte es diesen Fehler, als der Code war:

<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">

Als ich meinen Code dahingehend korrigierte:

<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">

Mein Fehler ist verschwunden.

Gokul Yesudoss
quelle
0

Das Problem scheint, dass Sie GETAnfragen nicht angemessen bearbeiten oder die Daten nicht direkt veröffentlichen, ohne zuerst das Formular zu erhalten.

Wenn Sie zum ersten Mal auf die Seite zugreifen, sendet der Client eine GETAnfrage. In diesem Fall sollten Sie HTML mit dem entsprechenden Formular senden.

Später füllt der Benutzer das Formular aus und sendet eine POSTAnfrage mit Formulardaten.

Ihre Ansicht sollte sein:

def deposit(request,account_num):
   if request.method == 'POST':
      form_=AccountForm(request.POST or None, instance=account)
      if form.is_valid(): 
          #handle form data
          return HttpResponseRedirect("/history/" + account_num + "/")
      else:
         #handle when form not valid
    else:
       #handle when request is GET (or not POST)
       form_=AccountForm(instance=account)

    return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))
Rohan
quelle
0

Überprüfen Sie, ob die Chrome-Cookies mit der Standardoption für Websites gesetzt sind. Ermöglichen das Einstellen lokaler Daten (empfohlen).

IWS
quelle
0

Methode 1:

from django.shortcuts import render_to_response
return render_to_response(
    'history.html',
    RequestContext(request, {
        'account_form': form,
    })

Methode 2:

from django.shortcuts import render
return render(request, 'history.html', {
    'account_form': form,
})

Da die Methode render_to_response möglicherweise Probleme mit Antwortcookies verursacht.

shenqi0920
quelle
0

Ich habe mich gerade einmal getroffen, die Lösung besteht darin, die Cookies zu leeren. Und kann beim Debuggen von SECRET_KEY geändert werden.

JunLe Meng
quelle
0

Durch das Löschen des Cache meines Browsers wurde dieses Problem für mich behoben. Ich hatte zwischen lokalen Entwicklungsumgebungen gewechselt, um das Django-Blog-Zinnia-Tutorial zu erstellen, nachdem ich an einem anderen Projekt gearbeitet hatte, als es passierte. Zuerst dachte ich, die Änderung der Reihenfolge von INSTALLED_APPS entsprechend dem Tutorial hätte dies verursacht, aber ich habe diese zurückgesetzt und konnte sie erst korrigieren, als der Cache geleert wurde.

Infosmith
quelle
0

Ich habe vorher Django 1.10 verwendet. Also war ich mit diesem Problem konfrontiert. Jetzt habe ich es auf Django 1.9 herabgestuft und es funktioniert gut.

indspecter
quelle
Mit 1.10.3 hatte ich dieses Problem. Ein Upgrade auf 1.10.6 hat es für mich behoben.
Mike Darmetko
0

Ich hatte den gleichen Fehler, in meinem Fall hilft das Hinzufügen von method_decorator:

from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator

method_decorator(csrf_protect)
def post(self, request):
    ...
Moszoro
quelle
0

Stellen Sie sicher, dass Ihr Django-Sitzungs-Backend in settings.py ordnungsgemäß konfiguriert ist. Dann versuchen Sie dies,

class CustomMiddleware(object):
  def process_request(self,request:HttpRequest):
      get_token(request)

Fügen Sie diese Middleware settings.pyunter MIDDLEWARE_CLASSESoder hinzuMIDDLEWARE abhängig von der Django-Version hinzu

get_token - Gibt das für ein POST-Formular erforderliche CSRF-Token zurück. Das Token ist ein alphanumerischer Wert. Ein neues Token wird erstellt, wenn noch keines festgelegt ist.

arp
quelle
-4

Verwenden Sie aus Ihrer Sicht den CSRF-Dekorator?

from django.views.decorators.csrf import csrf_protect

@csrf_protect def view(request, params): ....

abhishekgarg
quelle