Mógłbym skorzystać z pomocy w przestrzeganiu mechanizmu ochrony CSRF Django za pośrednictwem mojego postu AJAX. Postępowałem zgodnie ze wskazówkami tutaj:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
Skopiowałem dokładnie przykładowy kod AJAX, który mają na tej stronie:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Umieszczam alert drukujący zawartość getCookie('csrftoken')
przed xhr.setRequestHeader
połączeniem i rzeczywiście jest on wypełniony niektórymi danymi. Nie jestem pewien, jak sprawdzić, czy token jest poprawny, ale zachęcam mnie do znalezienia i wysłania czegoś.
Ale Django nadal odrzuca mój post AJAX.
Oto mój JavaScript:
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
Oto błąd, który widzę w Django:
[23 / lut / 2011 22:08:29] „POST / memorize / HTTP / 1.1” 403 2332
Jestem pewien, że coś mi umknęło, a może to proste, ale nie wiem, co to jest. Szukałem w SO i widziałem informacje o wyłączaniu sprawdzania CSRF dla mojego widoku za pomocą csrf_exempt
dekoratora, ale uważam to za nieatrakcyjne. Wypróbowałem to i działa, ale wolę, aby mój test POST działał w sposób, w jaki zaprojektowano Django, jeśli to możliwe.
Na wszelki wypadek pomocne jest to, co robi mój pogląd:
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))
Dziękuję za odpowiedzi!
Odpowiedzi:
Prawdziwe rozwiązanie
Ok, udało mi się wyśledzić problem. Jest w kodzie JavaScript (jak zasugerowałem poniżej).
Potrzebujesz tego:
zamiast kodu opublikowanego w oficjalnych dokumentach: https://docs.djangoproject.com/en/2.2/ref/csrf/
Działający kod pochodzi z tego wpisu Django: http://www.djangoproject.com/weblog/2011/feb/08/security/
Tak więc ogólne rozwiązanie to: „użyj modułu obsługi ajaxSetup zamiast modułu obsługi ajaxSend”. Nie wiem, dlaczego to działa. Ale to działa dla mnie :)
Poprzedni post (bez odpowiedzi)
Właściwie mam ten sam problem.
Występuje po aktualizacji do Django 1.2.5 - w Django 1.2.4 nie wystąpiły błędy z żądaniami AJAX POST (AJAX nie był w żaden sposób chroniony, ale działał dobrze).
Podobnie jak OP, wypróbowałem fragment kodu JavaScript opublikowany w dokumentacji Django. Korzystam z jQuery 1.5. Używam również oprogramowania pośredniego „django.middleware.csrf.CsrfViewMiddleware”.
Próbowałem postępować zgodnie z kodem oprogramowania pośredniego i wiem, że to się nie udaje:
i wtedy
to „if” jest prawdziwe, ponieważ „request_csrf_token” jest pusty.
Zasadniczo oznacza to, że nagłówek NIE jest ustawiony. Czy jest coś nie tak z tą linią JS:
?
Mam nadzieję, że podane szczegóły pomogą nam rozwiązać problem :)
źródło
ajaxSetup
zamiastajaxSend
biegania jest sprzeczne z dokumentami jQuery: api.jquery.com/jQuery.ajaxSetupJeśli używasz tej
$.ajax
funkcji, możesz po prostu dodaćcsrf
token do treści danych:źródło
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
csrfmiddlewaretoken: '{{ csrf_token }}'
do mojegodata
słownika w trakcie$.post
rozmowy.Dodaj ten wiersz do kodu jQuery:
i zrobione.
źródło
CSRF Failed: CSRF token missing or incorrect.
Problem polega na tym, że django oczekuje, że wartość z pliku cookie zostanie zwrócona jako część danych formularza. Kod z poprzedniej odpowiedzi pobiera javascript w celu wyszukania wartości pliku cookie i umieszczenia go w danych formularza. Jest to cudowny sposób na zrobienie tego z technicznego punktu widzenia, ale wygląda na trochę gadatliwego.
W przeszłości robiłem to po prostu, pobierając javascript do umieszczenia wartości tokena w danych postu.
Jeśli użyjesz {% csrf_token%} w swoim szablonie, otrzymasz wyemitowane ukryte pole formularza, które przenosi wartość. Ale jeśli użyjesz {{csrf_token}}, dostaniesz samą wartość tokena, dzięki czemu będziesz mógł użyć tego w javascript w ten sposób ....
Następnie możesz dołączyć to, z wymaganą nazwą klucza w haszu, a następnie przesłać jako dane do wywołania ajax.
źródło
window
obiekcie, dzięki czemu są one później dostępne. Nawet w plikach statycznych.{% csrf_token %}
Umieścić w html szablony wnętrze<form></form>
tłumaczy się na coś takiego:
więc dlaczego nie po prostu grep to w JS w ten sposób:
a następnie przekazać go np. wykonując test POST, np .:
źródło
Odpowiedź niekwotowa:
stosowanie:
źródło
Jeśli twój formularz poprawnie publikuje w Django bez JS, powinieneś być w stanie stopniowo ulepszać go za pomocą ajax bez żadnego hakowania lub niechlujnego przekazywania tokena csrf. Wystarczy serializować cały formularz, a to automatycznie pobierze wszystkie pola formularza, w tym ukryte pole csrf:
Przetestowałem to z Django 1.3+ i jQuery 1.5+. Oczywiście będzie to działać dla dowolnej formy HTML, nie tylko dla aplikacji Django.
źródło
Używaj Firefoksa z Firebug. Otwórz kartę „Konsola” podczas uruchamiania żądania ajax. Z
DEBUG=True
ciebie dostać nicejskiego django strony błędu jako odpowiedź i można nawet zobaczyć renderowany HTML w odpowiedzi ajax w zakładce konsoli.Wtedy dowiesz się, jaki jest błąd.
źródło
Przyjęta odpowiedź to najprawdopodobniej czerwony śledź. Różnica między Django 1.2.4 i 1.2.5 była wymagana dla tokena CSRF dla żądań AJAX.
Natknąłem się na ten problem na Django 1.3 i był on spowodowany nie ustawieniem pliku cookie CSRF . Django nie ustawi ciasteczka, chyba że będzie to konieczne. Tak więc strona wyłącznie lub w dużej mierze działająca na Django 1.2.4 potencjalnie nigdy nie wysłałaby tokena do klienta, a wtedy aktualizacja wymagająca tokena spowodowałaby błędy 403.
Idealna poprawka znajduje się tutaj: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form,
ale musisz poczekać na 1.4, chyba że to tylko dokumentacja nadążająca za kodem
Edytować
Zauważ też, że późniejsze dokumenty Django zauważają błąd w jQuery 1.5, więc upewnij się, że używasz 1.5.1 lub nowszego z sugerowanym kodem Django: http://docs.djangoproject.com/en/1.3/ref/contrib/csrf/# ajax
źródło
ensure_csrf_cookie
, który można owinąć wokół widoku, aby upewnić się, że wysyła ciasteczko.csrftoken
przede wszystkim nie ma ciasteczka, dzięki!Wygląda na to, że nikt nie wspomniał o tym, jak to zrobić w czystym JS za pomocą
X-CSRFToken
nagłówka{{ csrf_token }}
, więc oto proste rozwiązanie, w którym nie trzeba przeszukiwać plików cookie ani DOM:źródło
Ponieważ w bieżących odpowiedziach nie podano nigdzie, najszybszym rozwiązaniem, jeśli nie osadzasz js w szablonie, jest:
Umieść
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
przed odniesieniem do pliku script.js w szablonie, a następnie dodajcsrfmiddlewaretoken
dodata
słownika w pliku js:źródło
Właśnie spotkałem trochę inną, ale podobną sytuację. Nie jestem w 100% pewien, czy będzie to rozwiązanie twojego przypadku, ale rozwiązałem problem dla Django 1.3, ustawiając parametr POST „csrfmiddlewaretoken” z odpowiednim ciągiem wartości pliku cookie, który jest zwykle zwracany w postaci domowego kodu HTML przez Django system szablonów z tagiem „{% csrf_token%}”. Nie próbowałem na starszym Django, po prostu stało się i rozwiązałem na Django 1.3. Mój problem polegał na tym, że pierwsze żądanie przesłane przez Ajax z formularza zostało pomyślnie wykonane, ale druga próba z dokładnie tego samego z nie powiodła się, spowodowało stan 403, mimo że nagłówek „X-CSRFToken” jest również poprawnie umieszczony z wartością tokena CSRF jak w przypadku pierwszej próby. Mam nadzieję że to pomoże.
Pozdrowienia,
Hiro
źródło
możesz wkleić ten plik js do pliku HTML, pamiętaj, aby umieścić go przed inną funkcją js
źródło
Jeden token CSRF jest przypisany do każdej sesji (tj. Przy każdym logowaniu). Zanim więc chcesz uzyskać dane wprowadzone przez użytkownika i wysłać je jako wywołanie ajax do jakiejś funkcji chronionej przez dekorator csrf_protect, spróbuj znaleźć funkcje, które są wywoływane przed otrzymaniem tych danych od użytkownika. Np. Musi być renderowany szablon, na którym użytkownik wprowadza dane. Ten szablon jest renderowany przez jakąś funkcję. W tej funkcji możesz uzyskać token csrf w następujący sposób: csrf = request.COOKIES ['csrftoken'] Teraz przekaż tę wartość csrf w słowniku kontekstowym, dla którego renderowany jest dany szablon. Teraz w tym szablonie napisz ten wiersz: Teraz w swojej funkcji javascript, przed wysłaniem żądania ajax, napisz to: var csrf = $ ('# csrf'). val () to wybierze wartość tokena przekazanego do szablonu i zapisze go w zmiennej csrf. Teraz podczas wykonywania połączenia ajax w danych postu przekaż również tę wartość: „csrfmiddlewaretoken”: csrf
Będzie to działać, nawet jeśli nie wdrażasz formularzy django.
W rzeczywistości logika jest następująca: Potrzebujesz tokena, który możesz otrzymać z żądania. Musisz więc po prostu dowiedzieć się, jaka funkcja jest wywoływana natychmiast po zalogowaniu. Kiedy już będziesz mieć ten token, albo wykonaj kolejne wywołanie ajax, aby je zdobyć, albo przekaż je do szablonu dostępnego dla twojego ajax.
źródło
csrftoken: csrftoken
zamiastcsrfmiddlwaretoken: csrftoken
. Po zmianie zadziałało. Dziękidla kogoś, kto zetknie się z tym i próbuje debugować:
1) Kontrola django csrf (zakładając, że ją wysyłasz) jest tutaj
2) W moim przypadku
settings.CSRF_HEADER_NAME
ustawiono opcję „HTTP_X_CSRFTOKEN”, a moje wywołanie AJAX wysyłało nagłówek o nazwie „HTTP_X_CSRF_TOKEN”, więc rzeczy nie działały. Mógłbym to zmienić w wywołaniu AJAX lub ustawienie django.3) Jeśli zdecydujesz się zmienić to po stronie serwera, znajdź swoją lokalizację instalacji django i rzuć punkt przerwania w
csrf middleware
.f używaszvirtualenv
, będzie to coś w stylu:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
Następnie upewnij się, że
csrf
token został poprawnie pobrany z żądania.META4) Jeśli potrzebujesz zmienić nagłówek itp. - zmień tę zmienną w pliku ustawień
źródło
Jeśli ktoś zmaga się z axios, aby ta praca działała, pomogło mi to:
Źródło: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/
źródło
W moim przypadku problem dotyczył konfiguracji nginx, którą skopiowałem z serwera głównego na tymczasowy z wyłączeniem https, który nie jest potrzebny na drugim w tym procesie.
Musiałem skomentować te dwa wiersze w konfiguracji, aby znów działało:
źródło
Oto mniej szczegółowe rozwiązanie dostarczone przez Django:
Źródło: https://docs.djangoproject.com/en/1.11/ref/csrf/
źródło