Come disabilitare la convalida CSRF di Django?


111

Ho commentato il processore csrf e le linee middleware in 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 )

Ma quando utilizzo Ajax per inviare una richiesta, Django risponde ancora "il token csrf è errato o mancante" e, dopo aver aggiunto X-CSRFToken alle intestazioni, la richiesta ha esito positivo.

Che cosa sta succedendo qui ?


Risposte:


232

Se hai solo bisogno di alcune viste per non usare CSRF, puoi usare @csrf_exempt:

from django.views.decorators.csrf import csrf_exempt

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

Puoi trovare altri esempi e altri scenari nella documentazione di Django:


2
Ciao, @TheBronx, voglio davvero sapere perché la mia soluzione non funziona.
WoooHaaaa

1
scusa @MrROY Non so perché la tua soluzione non funziona. So solo che @csrf_exempfunziona perché l'ho usato di recente senza problemi. Spero che tu trovi la risposta.
Salvatorelab

6
@ MrROY, è una cosa da Django. La maggior parte delle cose funziona / non funziona solo perché c'è un'impostazione magica sepolta nel profondo del codice.
idursun

2
Un promemoria: se hai altri decoratori nella stessa vista l'ordine è rilevante: quindi inserisci prima @csrf_exempt.
Patrick Bassut

3
Hmm- forse una risposta tecnicamente corretta, ma sicuramente non quello che voleva l'OP o quello che stavo cercando.
Danny Staple

40

Per disabilitare CSRF per le viste basate sulla classe, ho funzionato quanto segue.
Utilizzando django 1.10 e python 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

In setting.pyMIDDLEWARE puoi semplicemente rimuovere / commentare questa riga:

'django.middleware.csrf.CsrfViewMiddleware',

1
questo funziona per me su Django 2.1 usando curl come client http.
terra

1
@xtrinch Assicurati di chiudere / riavviare completamente il processo del server. Non credo che l'auto-relaod raccolga il cambiamento
Basic

15

Per Django 2 :

from django.utils.deprecation import MiddlewareMixin


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

Quel middleware deve essere aggiunto settings.MIDDLEWAREquando appropriato (ad esempio nelle impostazioni di test).

Nota: l'impostazione non viene MIDDLEWARE_CLASSESpiù richiamata .


11

La risposta potrebbe essere inappropriata, ma spero che ti aiuti

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

Un middleware di questo tipo aiuta a eseguire il debug delle richieste e a controllare csrf nei server di produzione.


Hmm. Ho provato questo in Django 1.9.1. Rimosso il decoratore @csrf_exempt dal metodo e aggiunto il codice sopra. Ho ricevuto un 403 perché il cookie non è stato impostato.
Craig S. Anderson

11

Il problema qui è che SessionAuthentication esegue la propria convalida CSRF. Questo è il motivo per cui ottieni l'errore CSRF mancante anche quando il middleware CSRF viene commentato. Puoi aggiungere @csrf_exempt a ogni vista, ma se vuoi disabilitare CSRF e avere l'autenticazione della sessione per l'intera app, puoi aggiungere un middleware extra come questo -

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

Ho creato questa classe in myapp / middle.py Quindi importa questo middleware in Middleware in 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',

]

Funziona con DRF su django 1.11


3
Grazie per aver effettivamente dato una risposta alla domanda invece di pubblicare solo una soluzione.
ThaJay

5

Se vuoi disabilitarlo in Global, puoi scrivere un middleware personalizzato, come questo

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)

quindi aggiungi questa classe youappname.middlewarefilename.DisableCsrfCheckagli MIDDLEWARE_CLASSESelenchi, primadjango.middleware.csrf.CsrfViewMiddleware



0

@WoooHaaaa alcuni pacchetti di terze parti utilizzano il middleware "django.middleware.csrf.CsrfViewMiddleware". per esempio io uso django-rest-oauth e ho problemi come te anche dopo aver disabilitato quelle cose. forse questi pacchetti hanno risposto alla tua richiesta come nel mio caso, perché usi il decoratore di autenticazione e qualcosa del genere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.