Bagaimana cara menonaktifkan validasi CSRF Django?

111

Saya telah mengomentari prosesor csrf dan baris middleware di 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 )

Tetapi ketika saya menggunakan Ajax untuk mengirim permintaan, Django masih menjawab 'token csrf tidak benar atau hilang', dan setelah menambahkan X-CSRFToken ke tajuk, permintaan akan berhasil.

Apa yang terjadi disini ?

WoooHaaaa
sumber
Kemungkinan duplikat: stackoverflow.com/questions/1650941/…
Rohan

Jawaban:

232

Jika Anda hanya membutuhkan beberapa tampilan untuk tidak menggunakan CSRF, Anda dapat menggunakan @csrf_exempt:

from django.views.decorators.csrf import csrf_exempt

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

Anda dapat menemukan lebih banyak contoh dan skenario lainnya dalam dokumentasi Django:

Salvatorelab
sumber
2
Hai, @TheBronx, saya benar-benar ingin tahu mengapa solusi saya tidak berhasil.
WoooHaaaa
1
maaf @MrROY Saya tidak tahu mengapa solusi Anda tidak berfungsi. Saya hanya tahu itu @csrf_exempberfungsi seperti yang saya gunakan baru-baru ini tanpa masalah. Semoga Anda menemukan jawabannya.
Salvatorelab
6
@MrROY, Ini adalah hal Django. Kebanyakan hal bekerja / tidak berfungsi hanya karena ada pengaturan ajaib yang terkubur jauh di dalam basis kode.
idursun
2
Pengingat: jika Anda memiliki dekorator lain dalam tampilan yang sama, urutannya relevan: jadi tempatkan @csrf_exempt terlebih dahulu.
Patrick Bassut
3
Hmm- mungkin jawaban yang benar secara teknis, tetapi yang pasti bukan yang diinginkan OP atau yang saya cari.
Danny Staple
40

Untuk menonaktifkan CSRF untuk tampilan berbasis kelas, berikut ini berfungsi untuk saya.
Menggunakan django 1.10 dan 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')
Martijn ten Hoor
sumber
32

Di setting.pyMIDDLEWARE Anda cukup menghapus / mengomentari baris ini:

'django.middleware.csrf.CsrfViewMiddleware',
Rohit33
sumber
1
ini bekerja untuk saya di Django 2.1 menggunakan curl sebagai klien http.
tanah liat
1
@xtrinch Pastikan Anda sepenuhnya keluar / meluncurkan kembali proses server. Saya tidak berpikir auto-relaod mengambil perubahan
Dasar
15

Untuk Django 2 :

from django.utils.deprecation import MiddlewareMixin


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

Middleware itu harus ditambahkan settings.MIDDLEWAREjika sesuai (dalam pengaturan pengujian Anda misalnya).

Catatan: pengaturan tidak dipanggil MIDDLEWARE_CLASSESlagi.

François Constant
sumber
11

Jawabannya mungkin tidak tepat, tapi saya harap ini membantu Anda

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

Memiliki middleware seperti ini membantu untuk men-debug permintaan dan memeriksa csrf di server produksi.

naren
sumber
Hmm. Mencoba ini di Django 1.9.1. Menghapus dekorator @csrf_exempt dari metode dan menambahkan kode di atas. Mendapat 403 karena cookie belum disetel.
Craig S. Anderson
11

Masalahnya di sini adalah SessionAuthentication melakukan validasi CSRF-nya sendiri. Itulah mengapa Anda mendapatkan kesalahan CSRF yang hilang bahkan ketika CSRF Middleware diberi komentar. Anda dapat menambahkan @csrf_exempt ke setiap tampilan, tetapi jika Anda ingin menonaktifkan CSRF dan memiliki otentikasi sesi untuk seluruh aplikasi, Anda dapat menambahkan middleware tambahan seperti ini -

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

Saya membuat kelas ini di myapp / middle.py Kemudian impor middleware ini di Middleware di 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',

]

Itu bekerja dengan DRF pada django 1.11

Madhuri Gole
sumber
3
Terima kasih telah benar-benar memberikan jawaban atas pertanyaan daripada hanya memposting solusi.
ThaJay
5

Jika Anda ingin menonaktifkannya di Global, Anda dapat menulis middleware kustom, seperti ini

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)

lalu tambahkan kelas ini youappname.middlewarefilename.DisableCsrfCheckke MIDDLEWARE_CLASSESdaftar, sebelumnyadjango.middleware.csrf.CsrfViewMiddleware

JJP
sumber
0

@WoooHaaaa beberapa paket pihak ketiga menggunakan middleware 'django.middleware.csrf.CsrfViewMiddleware'. misalnya saya menggunakan django-rest-oauth dan saya memiliki masalah seperti Anda bahkan setelah menonaktifkannya. mungkin paket ini menanggapi permintaan Anda seperti kasus saya, karena Anda menggunakan dekorator otentikasi dan sesuatu seperti ini.

M.qaemi Qaemi
sumber