Saya tahu bahwa ada jawaban mengenai Django Rest Framework, tetapi saya tidak dapat menemukan solusi untuk masalah saya.
Saya memiliki aplikasi yang memiliki otentikasi dan beberapa fungsi. Saya menambahkan aplikasi baru ke dalamnya, yang menggunakan Django Rest Framework. Saya ingin menggunakan perpustakaan hanya di aplikasi ini. Saya juga ingin membuat permintaan POST, dan saya selalu menerima tanggapan ini:
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
Saya memiliki kode berikut:
# urls.py
from django.conf.urls import patterns, url
urlpatterns = patterns(
'api.views',
url(r'^object/$', views.Object.as_view()),
)
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
class Object(APIView):
@csrf_exempt
def post(self, request, format=None):
return Response({'received data': request.data})
Saya ingin menambahkan API tanpa mempengaruhi aplikasi saat ini. Jadi pertanyaan saya adalah bagaimana saya bisa menonaktifkan CSRF hanya untuk aplikasi ini?
django
django-rest-framework
csrf
django-csrf
Irene Texas
sumber
sumber
Jawaban:
Mengapa kesalahan ini terjadi?
Ini terjadi karena
SessionAuthentication
skema default yang digunakan oleh DRF. DRFSessionAuthentication
menggunakan kerangka sesi Django untuk otentikasi yang membutuhkan CSRF untuk diperiksa.Saat Anda tidak menentukan apa pun
authentication_classes
di view / viewset Anda, DRF menggunakan kelas otentikasi ini sebagai default.Karena DRF perlu mendukung otentikasi berbasis sesi dan non-sesi ke tampilan yang sama, DRF memberlakukan pemeriksaan CSRF hanya untuk pengguna yang diautentikasi. Ini berarti bahwa hanya permintaan terautentikasi yang memerlukan token CSRF dan permintaan anonim dapat dikirim tanpa token CSRF.
Jika Anda menggunakan API gaya AJAX dengan SessionAuthentication, Anda harus menyertakan token CSRF yang valid untuk setiap panggilan metode HTTP "tidak aman", seperti
PUT, PATCH, POST or DELETE
permintaan.Lalu apa yang harus dilakukan?
Sekarang untuk menonaktifkan pemeriksaan csrf, Anda dapat membuat kelas otentikasi khusus
CsrfExemptSessionAuthentication
yang diturunkan dariSessionAuthentication
kelas default . Di kelas otentikasi ini, kami akan menggantienforce_csrf()
pemeriksaan yang terjadi di dalam fileSessionAuthentication
.Dalam pandangan Anda, maka Anda dapat menentukan
authentication_classes
menjadi:Ini harus menangani kesalahan csrf.
sumber
Solusi yang lebih mudah:
Di views.py, gunakan tanda kurung CsrfExemptMixin dan authentication_classes:
sumber
Ubah urls.py
Jika Anda mengelola rute Anda di urls.py, Anda bisa menggabungkan rute yang Anda inginkan dengan csrf_exempt () untuk mengecualikannya dari middleware verifikasi CSRF.
Atau, sebagai Dekorator Beberapa orang mungkin menganggap penggunaan dekorator @csrf_exempt lebih sesuai untuk kebutuhan mereka
misalnya,
harus menyelesaikan Pekerjaan!
sumber
Untuk semua yang tidak menemukan jawaban yang membantu. Ya, DRF secara otomatis menghapus perlindungan CSRF jika Anda tidak menggunakan
SessionAuthentication
KELAS OTENTIKASI, misalnya, banyak pengembang hanya menggunakan JWT:Tetapi masalah
CSRF not set
dapat terjadi karena beberapa alasan lain, misalnya Anda tidak menambahkan jalur dengan benar ke tampilan Anda:dari pada
sumber
Saya mencoba beberapa jawaban di atas dan merasa membuat kelas terpisah agak berlebihan.
Sebagai referensi, saya mengalami masalah ini saat mencoba memperbarui metode tampilan berbasis fungsi ke metode tampilan berbasis kelas untuk pendaftaran pengguna.
Saat menggunakan tampilan berbasis kelas (CBVs) dan Django Rest Framework (DRF), Mewarisi dari kelas ApiView dan setel permission_classes dan authentication_classes ke tupel kosong. Temukan contoh di bawah ini.
sumber
Jika Anda tidak ingin menggunakan otentikasi berbasis sesi, Anda dapat menghapus
Session Authentication
dari REST_AUTHENTICATION_CLASSES dan itu akan secara otomatis menghapus semua masalah berbasis csrf. Namun dalam kasus ini, API yang dapat dijelajahi mungkin tidak berfungsi.Selain itu kesalahan ini seharusnya tidak datang bahkan dengan otentikasi sesi. Anda harus menggunakan otentikasi khusus seperti TokenAuthentication untuk apis Anda dan pastikan untuk mengirim
Accept:application/json
danContent-Type:application/json
(asalkan Anda menggunakan json) dalam permintaan Anda bersama dengan token otentikasi.sumber
Anda perlu menambahkan ini untuk mencegah otentikasi sesi default: (settings.py)
Kemudian: (views.py)
sumber
Saya terpukul dengan masalah yang sama. Saya mengikuti referensi ini dan berhasil. Solusinya adalah dengan membuat middleware
Tambahkan file disable.py di salah satu aplikasi Anda (dalam kasus saya ini adalah 'myapp')
Dan tambahkan middileware ke MIDDLEWARE_CLASSES
sumber
Jika Anda menggunakan lingkungan virtual eksklusif untuk aplikasi Anda, Anda dapat menggunakan pendekatan berikut tanpa aplikasi lain yang efektif.
Apa yang Anda amati terjadi karena
rest_framework/authentication.py
memiliki kode ini dalamauthenticate
metodeSessionAuthentication
kelas:Anda dapat mengubah
Request
kelas agar properti dipanggilcsrf_exempt
dan menginisialisasinya di dalam kelas View masing-masingTrue
jika Anda tidak ingin pemeriksaan CSRF. Sebagai contoh:Selanjutnya, ubah kode di atas sebagai berikut:
Ada beberapa perubahan terkait yang harus Anda lakukan di
Request
kelas. Implementasi lengkap tersedia di sini (dengan deskripsi lengkap): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7edsumber
Solusi saya ditampilkan pukulan. Hiasi saja kelasku.
sumber
Saat menggunakan REST API POST, tidak adanya header permintaan X-CSRFoken dapat menyebabkan kesalahan tersebut. Dokumentasi Django menyediakan kode contoh untuk mendapatkan dan menyetel nilai token CSRF dari JS.
Seperti yang ditunjukkan dalam jawaban di atas, pemeriksaan CSRF terjadi saat SessionAuthentication digunakan. Pendekatan lain adalah dengan menggunakan TokenAuthentication, tetapi perlu diingat bahwa ini harus ditempatkan pertama kali dalam daftar DEFAULT_AUTHENTICATION_CLASSES pengaturan REST_FRAMEWORK.
sumber
Ini juga bisa menjadi masalah selama serangan DNS Rebinding .
Di antara perubahan DNS, ini juga bisa menjadi faktor. Menunggu sampai DNS benar-benar habis akan menyelesaikan ini jika berfungsi sebelum masalah / perubahan DNS.
sumber