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 ?

WoooHaaaa
źródło
Możliwy duplikat: stackoverflow.com/questions/1650941/…
Rohan

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:

Salvatorelab
źródło
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')
Martijn ten Hoor
źródło
32

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

'django.middleware.csrf.CsrfViewMiddleware',
Rohit33
źródło
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 .

François Constant
źródło
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.

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

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

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

M.qaemi Qaemi
źródło