Jak wyłączyć walidację CSRF Django?


112

Skomentowałem linie procesora csrf i oprogramowania pośredniego w settings.py:

122 
123 TEMPLATE_CONTEXT_PROCESSORS = (
124     'django.contrib.auth.context_processors.auth',
125 #    'django.core.context_processors.csrf',
126     'django.core.context_processors.request',
127     'django.core.context_processors.static',
128     'cyathea.processors.static',
129 )
130 
131 MIDDLEWARE_CLASSES = (
132     'django.middleware.common.CommonMiddleware',
133     'django.contrib.sessions.middleware.SessionMiddleware',
134 #    'django.middleware.csrf.CsrfViewMiddleware',
135     'django.contrib.auth.middleware.AuthenticationMiddleware',
136     'django.contrib.messages.middleware.MessageMiddleware',
137     'django.middleware.locale.LocaleMiddleware',
138     # Uncomment the next line for simple clickjacking protection:
139     # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
140 )

Ale kiedy używam Ajax do wysyłania żądania, Django nadal odpowiada `` token csrf jest nieprawidłowy lub brakuje go '', a po dodaniu X-CSRFToken do nagłówków żądanie się powiedzie.

Co tu się dzieje ?


Odpowiedzi:


233

Jeśli potrzebujesz tylko widoków, aby nie używać CSRF, możesz użyć @csrf_exempt:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

Więcej przykładów i innych scenariuszy można znaleźć w dokumentacji Django:


2
Cześć @TheBronx, naprawdę chcę wiedzieć, dlaczego moje rozwiązanie nie działa.
— WoooHaaaa

1
przepraszam @MrROY Nie wiem, dlaczego twoje rozwiązanie nie działa. Wiem tylko, że @csrf_exempdziała tak, jak ostatnio bez problemów. Mam nadzieję, że znajdziesz odpowiedź.
— Salvatorelab

6
@MrROY, to rzecz Django. Większość rzeczy działa / nie działa tylko dlatego, że istnieje magiczne ustawienie ukryte głęboko w bazie kodu.
— idursun

2
Przypomnienie: jeśli masz inne dekoratory w tym samym widoku, kolejność jest istotna: więc najpierw umieść @csrf_exempt.
— Patrick Bassut

3
Hmm- może technicznie poprawna odpowiedź, ale na pewno nie to, czego chciał OP lub czego ja szukałem.
— Danny Staple,

40

Aby wyłączyć CSRF dla widoków opartych na klasach, działało dla mnie następujące rozwiązanie.
Używając django 1.10 i Pythona 3.5.2

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

@method_decorator(csrf_exempt, name='dispatch')
class TestView(View):
    def post(self, request, *args, **kwargs):
        return HttpResponse('Hello world')

32

W setting.pyoprogramowaniu MIDDLEWARE możesz po prostu usunąć / skomentować tę linię:

'django.middleware.csrf.CsrfViewMiddleware',

1
to działa dla mnie w Django 2.1 używając curl jako klienta http.
— glina

1
@xtrinch Upewnij się, że całkowicie zamknąłeś / ponownie uruchomiłeś proces serwera. Nie sądzę, aby automatyczne ponowne przełączanie odbierało zmianę
— Podstawowy

15

Dla Django 2 :

from django.utils.deprecation import MiddlewareMixin


class DisableCSRF(MiddlewareMixin):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

To oprogramowanie pośredniczące należy dodać w settings.MIDDLEWARErazie potrzeby (na przykład w ustawieniach testu).

Uwaga: to ustawienie nie jest MIDDLEWARE_CLASSESjuż wywoływane .


11

Odpowiedź może być niewłaściwa, ale mam nadzieję, że ci pomoże

class DisableCSRFOnDebug(object):
    def process_request(self, request):
        if settings.DEBUG:
            setattr(request, '_dont_enforce_csrf_checks', True)

Posiadanie takiego oprogramowania pośredniego pomaga debugować żądania i sprawdzać csrf na serwerach produkcyjnych.


Hmm. Wypróbowałem to w Django 1.9.1. Usunięto dekorator @csrf_exempt z metody i dodano powyższy kod. Otrzymano 403, ponieważ plik cookie nie został ustawiony.
— Craig S. Anderson

11

Problem polega na tym, że SessionAuthentication wykonuje własną walidację CSRF. Dlatego pojawia się błąd braku CSRF, nawet jeśli oprogramowanie pośredniczące CSRF jest komentowane. Możesz dodać @csrf_exempt do każdego widoku, ale jeśli chcesz wyłączyć CSRF i mieć uwierzytelnianie sesji dla całej aplikacji, możesz dodać dodatkowe oprogramowanie pośredniczące, takie jak to -

class DisableCSRFMiddleware(object):

def __init__(self, get_response):
    self.get_response = get_response

def __call__(self, request):
    setattr(request, '_dont_enforce_csrf_checks', True)
    response = self.get_response(request)
    return response

Utworzyłem tę klasę w myapp / middle.py Następnie zaimportuj to oprogramowanie pośrednie w Middleware w settings.py

MIDDLEWARE = [
    'django.middleware.common.CommonMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',
    'myapp.middle.DisableCSRFMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

Działa to z DRF w django 1.11


3
Dziękuję za udzielenie odpowiedzi na pytanie, zamiast po prostu opublikować rozwiązanie.
— ThaJay

5

Jeśli chcesz go wyłączyć w Global, możesz napisać niestandardowe oprogramowanie pośredniczące, w ten sposób

from django.utils.deprecation import MiddlewareMixin

class DisableCsrfCheck(MiddlewareMixin):

    def process_request(self, req):
        attr = '_dont_enforce_csrf_checks'
        if not getattr(req, attr, False):
            setattr(req, attr, True)

następnie dodaj tę klasę youappname.middlewarefilename.DisableCsrfCheckdo MIDDLEWARE_CLASSESlist, wcześniejdjango.middleware.csrf.CsrfViewMiddleware



0

@WoooHaaaa Niektóre pakiety innych firm używają oprogramowania pośredniego „django.middleware.csrf.CsrfViewMiddleware”. na przykład używam django-rest-oauth i mam problem jak ty, nawet po wyłączeniu tych rzeczy. może te pakiety odpowiedziały na twoje żądanie jak mój przypadek, ponieważ używasz dekoratora uwierzytelniania i coś w tym rodzaju.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.