Plik cookie Django CSRF nie jest ustawiony

85

Mam jakiś problem od jakiegoś czasu, doświadczam CSRF Cookie nie jest ustawiony. Proszę spojrzeć na poniższe kody

Pyton

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

W kodzie HTML jest kod

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>

Utknąłem, wyczyściłem już plik cookie, użyłem innej przeglądarki, ale nadal nie ustawiłem pliku cookie csrf.


źródło
Czy masz CsrfViewMiddlewarew swoim MIDDLEWARE_CLASSESotoczeniu?
alecxe
Dodaj {%csrf_token%}swój formularz w szablonie.
Rohan
4
@Rohan już tam jest, zobacz pytanie.
alecxe
1
Tak, mam już CsrfViewMiddleware i mam już csrf_token w swoim formularzu
Korzystałem z modułu Django cors i uzyskiwałem do niego dostęp przez ReactJS. (Oba znajdowały się na hoście lokalnym). Miałem też ten problem z OP. Znalazłem dla mnie, że dodanie credentials: 'include'do żądania POST, a następnie dodanie RÓWNIEŻ w settings.py django: CORS_ALLOW_CREDENTIALS = Truewydaje się, że rozwiązało problem bez konieczności dodawania @csrf_exemptdo widoku. Właściwie to jest w dokumentach ... pypi.org/project/django-cors-headers-multi * Wiem, że dotyczy to jednego z powyższych pytań, ale nie mogę jeszcze komentować i mam nadzieję, że chcę zaoszczędzić komuś innemu czas zabrał mnie do znalezienia t
DW

Odpowiedzi:

134

Może się to również zdarzyć, jeśli CSRF_COOKIE_SECURE = Truejest ustawione i uzyskujesz dostęp do witryny w sposób niezabezpieczony lub jeśli CSRF_COOKIE_HTTPONLY = Truejest ustawione tak, jak podano tutaj i tutaj

Druska
źródło
10
Dzięki! To samo dotyczy SESSION_COOKIE_SECURE = True.
NonameSL
74
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")
Евгений Смирнов
źródło
60
Całkowite wyłączenie mechanizmu zabezpieczeń nie jest dobrym sposobem na naprawienie błędu.
Guillaume Algis
2
Jeśli używasz cookiecutter-django w 2017 roku, jest to poprawna odpowiedź w produkcji.
André Duarte
1
Dlaczego z ciekawości?
Patrick Gallagher
3
Ta odpowiedź nie sugeruje „całkowitego wyłączenia mechanizmu bezpieczeństwa”, a jedynie mówi, jak to zrobić w pojedynczym przypadku, w którym możesz nie być w stanie użyć tokenu CSRF. To jest mój przypadek, w którym muszę zaoferować akcję POST klientowi zewnętrznemu.
mariotomo
Jest to element typu TODO, którego używam w fazie rozwoju, kiedy nie możesz dostarczyć tokenu csrf z interfejsu użytkownika. Ale z pewnością nie jest to zalecane w przypadku aplikacji na żywo.
Aman Madan
24

Jeśli używasz interfejsu API pobierania HTML5 do wysyłania żądań POST jako zalogowany użytkownik i otrzymujesz Forbidden (CSRF cookie not set.), może to być spowodowane tym , że domyślnie fetchnie zawiera plików cookie sesji, co powoduje, że Django myśli, że jesteś innym użytkownikiem niż ten, który załadował stronę .

Możesz dołączyć token sesji, przekazując opcję credentials: 'include'pobierania:

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
źródło
czy mogę wiedzieć, jaka jest ta metoda Header (), którą utworzyłeś? czy to globalna metoda javascript?
Abz Rockers
@AbzRockers: Tak, Headersto globalny interfejs javascript, część HTML5 Fetch API. developer.mozilla.org/en-US/docs/Web/API/Headers
user85461
13

Z tego Możesz go rozwiązać, dodając dekorator sure_csrf_cookie do swojego widoku

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

jeśli ta metoda nie działa. spróbujesz skomentować csrf w oprogramowaniu pośrednim. i przetestuj ponownie.

dscanon
źródło
5

Podobną sytuację natknąłem się podczas pracy z DRF, rozwiązaniem było dodanie metody .as_view () do widoku w urls.py

Pratik Mhatre
źródło
Byłoby lepiej, gdybyś dołączył również jakiś kod
Alex Jolig
1
@AlexJolig właśnie zmierzył się z tym samym problemem, problem polegał na tym, że zapomniałem dodać .as_view()później mojego ApiView, więc kod wyglądał tak: urlpatterns += path('resource', ResourceView)I tak powinno wyglądać: urlpatterns += path('resource', ResourceView.as_view())
Alveona
4

Jeśli używasz DRF, sprawdź, czy twoje wzorce url są poprawne, być może zapomniałeś .as_view():

A więc jak wyglądał mój kod:

urlpatterns += path('resource', ResourceView) 

I tak powinno być:

urlpatterns += path('resource', ResourceView.as_view())
Alveona
źródło
1

spróbuj sprawdzić, czy masz zainstalowane w settings.py

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

W szablonie dane są formatowane za pomocą csrf_token:

<form>{% csrf_token %}
</form>
drabo2005
źródło
nie mam całego twojego kodu, ale wydaje mi się, że sprawa jest tutaj: def deposit (request, account_num): zmieniono go na def deposit (request): i znajdź sposób na oddzwonienie do account_num. teraz będzie zależeć, czy account_num jest polem tabeli, czy zmienną.
drabo2005
To jest zmienna {{account_num}}, ale jak to wpływa na token csrf?
Uważam, że token csrf odnosił się tylko do żądania, więc nie może zweryfikować ani obsłużyć tego, co dzieje się ze zmienną tutaj. sprawdź djangoproject.com może być, że możesz uzyskać poprawną odpowiedź na temat csrf_token.
drabo2005
1

Ten problem pojawił się ponownie niedawno z powodu błędu w samym Pythonie.

http://bugs.python.org/issue22931

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

Wśród wersji, których to dotyczy, były 2.7.8 i 2.7.9. Plik cookie nie został poprawnie odczytany, jeśli jedna z wartości zawierała[ znak.

Aktualizacja Pythona (2.7.10) rozwiązuje problem.

sbaechler
źródło
1

Dzieje się tak również wtedy, gdy nie ustawisz akcji formularza.
U mnie pokazywał ten błąd, gdy kod był:

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

Kiedy poprawiłem mój kod w ten sposób:

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

mój błąd zniknął.

Gokul Yesudoss
źródło
0

Wygląda na to, że nie obsługujesz GETprawidłowo wniosków lub nie przesyłasz bezpośrednio danych bez uprzedniego uzyskania formularza.

Przy pierwszym wejściu na stronę klient wyśle GETzapytanie, w takim przypadku należy wysłać html z odpowiednim formularzem.

Później użytkownik wypełnia formularz i wysyła POST zapytanie z danymi formularza.

Twój pogląd powinien wyglądać następująco:

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
źródło
0

Sprawdź, czy pliki cookie Chrome są ustawione z domyślną opcją dla witryn internetowych. Zezwalaj na ustawianie danych lokalnych (zalecane).

IWS
źródło
0

Metoda 1:

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

Metoda 2:

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

Ponieważ metoda render_to_response może powodować problem z plikami cookie odpowiedzi.

shenqi0920
źródło
0

Spotkałem się tylko raz, rozwiązaniem jest opróżnienie ciasteczek. I może zostać zmieniony podczas debugowania związanego z SECRET_KEY.

JunLe Meng
źródło
0

Wyczyszczenie pamięci podręcznej przeglądarki rozwiązało ten problem. Przełączałem się między lokalnymi środowiskami programistycznymi, aby wykonać samouczek django-blog-zinnia po pracy nad innym projektem, kiedy to się stało. Na początku myślałem, że zmiana kolejności INSTALLED_APPS w celu dopasowania do samouczka spowodowała to, ale ustawiłem je z powrotem i nie mogłem tego poprawić, dopóki nie wyczyściłem pamięci podręcznej.

infosmith
źródło
0

Wcześniej używałem Django 1.10, więc miałem ten problem. Teraz obniżyłem go do Django 1.9 i działa dobrze.

nieprzyzwoity
źródło
Używając 1.10.3 miałem ten problem. Aktualizacja do wersji 1.10.6 rozwiązała problem.
Mike Darmetko
0

Miałem ten sam błąd, w moim przypadku dodanie method_decorator pomaga:

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

method_decorator(csrf_protect)
def post(self, request):
    ...
moszoro
źródło
0

Upewnij się, że backend sesji django jest poprawnie skonfigurowany w settings.py. Następnie spróbuj tego,

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

Dodaj to oprogramowanie pośrednie settings.pypod MIDDLEWARE_CLASSESlub w MIDDLEWAREzależności od wersji django

get_token - zwraca token CSRF wymagany dla formularza POST. Token jest wartością alfanumeryczną. Nowy token jest tworzony, jeśli nie został jeszcze ustawiony.

arp
źródło
-4

Czy Twoim zdaniem używasz dekoratora CSRF?

from django.views.decorators.csrf import csrf_protect

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

abhishekgarg
źródło