Django बाकी फ्रेमवर्क सीएसआरएफ को हटा दें


111

मुझे पता है कि Django रेस्ट फ्रेमवर्क के बारे में जवाब हैं, लेकिन मैं अपनी समस्या का हल नहीं ढूंढ सका।

मेरे पास एक एप्लिकेशन है जिसमें प्रमाणीकरण और कुछ कार्यक्षमता है। मैंने इसमें एक नया ऐप जोड़ा, जो Django रेस्ट फ्रेमवर्क का उपयोग करता है। मैं इस ऐप में केवल लाइब्रेरी का उपयोग करना चाहता हूं। इसके अलावा, मैं POST अनुरोध करना चाहता हूं, और मुझे हमेशा यह प्रतिक्रिया मिलती है:

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

मेरे पास निम्नलिखित कोड हैं:

# 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})

मैं वर्तमान एप्लिकेशन को प्रभावित किए बिना एपीआई जोड़ना चाहता हूं। तो मेरे सवाल हैं कि मैं केवल इस ऐप के लिए CSRF को कैसे अक्षम कर सकता हूं?


आप पहले से ही @csrf_exempt टोकन का उपयोग कर रहे हैं। आप इसे पूरे दृश्य पर उपयोग कर सकते हैं। कि काम नहीं करना चाहिए?
मुकेश

नहीं, मुझे अभी भी विवरण मिला है: "CSRF विफल: CSRF टोकन गायब या गलत है।" संदेश। मैंने उन उत्तरों से निष्कर्ष निकाला जो मुझे डिफ़ॉल्ट प्रमाणीकरण को हटा देना चाहिए।
आइरीन टेक्सास

1
मैं टोकन प्रमाणीकरण का उपयोग करके एक बहुत ही समान स्थिति में चल रहा था। उसी नाव में किसी और के लिए: stackoverflow.com/questions/34789301/…
The Brewmaster

जवाबों:


218

यह त्रुटि क्यों हो रही है?

SessionAuthenticationडीआरएफ द्वारा उपयोग की जाने वाली डिफ़ॉल्ट योजना के कारण ऐसा हो रहा है । DRF SessionAuthenticationप्रमाणीकरण के लिए Django के सत्र के ढांचे का उपयोग करता है जिसके लिए CSRF को जांचना आवश्यक है।

जब आप authentication_classesअपने दृश्य / दृश्य में किसी को परिभाषित नहीं करते हैं , तो डीआरएफ इस प्रमाणीकरण कक्षाओं को डिफ़ॉल्ट के रूप में उपयोग करता है।

'DEFAULT_AUTHENTICATION_CLASSES'= (
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication'
),

चूंकि DRF को सत्र और गैर-सत्र आधारित प्रमाणीकरण दोनों को समान विचारों के लिए समर्थन देने की आवश्यकता है, यह केवल प्रमाणीकृत उपयोगकर्ताओं के लिए CSRF जाँच को लागू करता है। इसका अर्थ है कि केवल प्रमाणित अनुरोधों में CSRF टोकन की आवश्यकता होती है और CSRF टोकन के बिना अनाम अनुरोध भेजे जा सकते हैं।

यदि आप SAXAuthentication के साथ AJAX शैली API का उपयोग कर रहे हैं, तो आपको किसी भी "असुरक्षित" HTTP पद्धति कॉल के लिए एक मान्य CSRF टोकन शामिल करने की आवश्यकता होगी, जैसे PUT, PATCH, POST or DELETEअनुरोध।

फिर क्या करें?

अब csrf चेक को डिसेबल करने के लिए, आप एक कस्टम ऑथेंटिकेशन क्लास बना सकते हैं CsrfExemptSessionAuthenticationजो डिफॉल्ट SessionAuthenticationक्लास से निकलता है । इस प्रमाणीकरण वर्ग में, हम ओवरराइड करेंगेenforce_csrf() चेक जो वास्तविक के अंदर हो रहा था SessionAuthentication

from rest_framework.authentication import SessionAuthentication, BasicAuthentication 

class CsrfExemptSessionAuthentication(SessionAuthentication):

    def enforce_csrf(self, request):
        return  # To not perform the csrf check previously happening

आपके विचार में, तब आप परिभाषित कर सकते हैं authentication_classes :

authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

यह सीएसआरएफ त्रुटि को संभालना चाहिए।


10
क्षमा करें, शायद मैं इस बिंदु से चूक गया, लेकिन सीएसआरएफ सुरक्षा को बायपास / अक्षम करने के लिए सुरक्षा जोखिम नहीं है?
पाओलो

1
@Paolo OP को किसी विशेष API के लिए CSRF प्रमाणीकरण को अक्षम करने की आवश्यकता है। लेकिन हां, सीएसआरएफ सुरक्षा को अक्षम करने के लिए इसका एक सुरक्षा जोखिम है। यदि किसी को किसी विशेष उपयोग के मामले में सत्र प्रमाणीकरण को अक्षम करना है, तो वह इस समाधान का उपयोग कर सकता है।
राहुल गुप्ता

अरे @RahulGupta - क्या व्यू पर csrf_exempt डेकोरेटर के लिए जांच करने का कोई तरीका नहीं है, और फिर केवल enforce_csrf को उन दृश्यों के लिए अक्षम करें?
अभिषेक

@Abhishek शायद तुम नीचे के लिए देख रहे हैं ans bixente57 द्वारा। यह कस्टम दृश्य के लिए csrf को निष्क्रिय करता है।
राहुल गुप्ता

1
@RahulGupta यदि आप enforce_csrf नहीं करना चाहते हैं, तो सबसे अच्छा तरीका क्या होगा?
गेमर

21

आसान समाधान:

Views.py में, CsrfExemptMixin और प्रमाणीकरण_क्लास के ब्रेसिज़ का उपयोग करें:

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
from braces.views import CsrfExemptMixin


class Object(CsrfExemptMixin, APIView):
    authentication_classes = []

    def post(self, request, format=None):
        return Response({'received data': request.data})

1
धन्यवाद, इस मुद्दे का सबसे आसान समाधान है। Oauth2_provider और टोकन का उपयोग करके मेरी एपी।
डाट टीटी

1
आह्ह्ह यार। मेरे पास CsrfExemptMixin था, लेकिन प्रमाणीकरण_क्लासेस = [] नहीं था। धन्यवाद!
मैजिकलैम्प

FYI करें, Auth_classes लाइन की कुंजी लगती है। CsrfExemptMixin के साथ या बिना मेरे लिए समान काम करता है।
दश्द्रुम

14

Urls.py संशोधित करें

यदि आप urls.py में अपने मार्गों का प्रबंधन करते हैं, तो आप CSRF सत्यापन मिडलवेयर से बाहर करने के लिए अपने इच्छित मार्गों को csrf_exempt () के साथ लपेट सकते हैं।

from django.conf.urls import patterns, url
    from django.views.decorators.csrf import csrf_exempt
    import views

urlpatterns = patterns('',
    url(r'^object/$', csrf_exempt(views.ObjectView.as_view())),
    ...
)

वैकल्पिक रूप से, एक सज्जाकार के रूप में कुछ अपनी जरूरतों के लिए अधिक उपयुक्त @csrf_exempt डेकोरेटर का उपयोग कर सकते हैं

उदाहरण के लिए,

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

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

नौकरी मिलनी चाहिए!


कोड के लिए कुछ स्पष्टीकरण एक बेहतर जवाब के लिए करना होगा।
chevybow

@chevybow वास्तव में क्षमा करें, मैं वास्तव में समुदाय के लिए नया हूं। वास्तव में इसकी एक सज्जाकार Django के एक निश्चित दृश्य के लिए CSRF को निष्क्रिय करने के लिए
सैयद फैजान

यह मेरे लिए python3 और django 1.11 के साथ काम करता है और सबसे आसान लगता है!
मदनस

12

उन सभी के लिए जिन्हें एक उपयोगी उत्तर नहीं मिला। यदि आप SessionAuthenticationAUTHENTICATION CLASS का उपयोग नहीं करते हैं तो DRF स्वतः CSRF सुरक्षा हटा देता है , उदाहरण के लिए, कई डेवलपर्स केवल WWT का उपयोग करते हैं:

'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),

लेकिन समस्या CSRF not setकिसी अन्य कारण से हो सकती है, छूटने के लिए आपने सही तरीके से आपके द्वारा जोड़े गए पथ को नहीं देखा है:

url(r'^api/signup/', CreateUserView),  # <= error! DRF cant remove CSRF because it is not as_view that does it!

के बजाय

url(r'^api/signup/', CreateUserView.as_view()),

8

मैंने ऊपर दिए गए कुछ जवाबों की कोशिश की और लगा कि एक अलग वर्ग बनाना थोड़ा मुश्किल था।

संदर्भ के लिए, मैं इस समस्या में भाग लिया जब उपयोगकर्ता पंजीकरण के लिए एक वर्ग आधारित दृश्य विधि के लिए एक फ़ंक्शन आधारित दृश्य विधि को अद्यतन करने का प्रयास कर रहा था।

क्लास-बेस्ड-व्यूज़ (CBVs) और Django रेस्ट फ्रेमवर्क (DRF) का उपयोग करते समय, ApiView क्लास से इनहेरिट करें और खाली ट्यूपल पर अनुमति_क्लास और ऑथेंटिकेशन_क्लास सेट करें। नीचे एक उदाहरण खोजें।

class UserRegistrationView(APIView):

    permission_classes = ()
    authentication_classes = ()

    def post(self, request, *args, **kwargs):

        # rest of your code here

7

यदि आप सत्र आधारित प्रमाणीकरण का उपयोग नहीं करना चाहते हैं, तो आप Session AuthenticationREST_AUTHENTICATION_CLASSES से हटा सकते हैं और यह स्वतः ही सभी सीएसआरएफ आधारित मुद्दों को हटा देगा। लेकिन उस स्थिति में शायद ब्राउस करने योग्य एप काम न करें।

इस त्रुटि के अलावा सत्र प्रमाणीकरण के साथ भी नहीं आना चाहिए। आपको अपने प्रमाणीकरण के लिए टोकन प्रमाणीकरण की तरह कस्टम प्रमाणीकरण का उपयोग करना चाहिए और प्रमाणीकरण टोकन के साथ अपने अनुरोधों में भेजना Accept:application/jsonऔर Content-Type:application/jsonप्रदान करना सुनिश्चित करें (बशर्ते आप json का उपयोग कर रहे हों)।


4

डिफ़ॉल्ट सत्र प्रमाणीकरण को रोकने के लिए आपको इसे जोड़ना होगा: (settings.py)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated', 
    )
}

फिर: (विचार करें)

from rest_framework.permissions import AllowAny

class Abc(APIView):
    permission_classes = (AllowAny,)

    def ...():

3

मैं उसी समस्या से त्रस्त हूं। मैंने इस संदर्भ का अनुसरण किया और इसने काम किया। समाधान एक मिडलवेयर बनाना है

अपने किसी एप्लिकेशन में अक्षम करें (अपने मामले में यह 'myapp' है)

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

और MIDDLEWARE_CLASSES में मिडिलवेयर जोड़ें

MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)

4
यह आपकी संपूर्ण वेबसाइट को CSRF के हमलों का शिकार बना देगा। en.wikipedia.org/wiki/Cross-site_request_forgery
जीनो

1

यदि आप अपने एप्लिकेशन के लिए अनन्य वर्चुअल वातावरण का उपयोग कर रहे हैं, तो आप किसी अन्य एप्लिकेशन को प्रभावी किए बिना निम्नलिखित दृष्टिकोण का उपयोग कर सकते हैं।

आपने जो देखा वह इसलिए होता है क्योंकि rest_framework/authentication.pyइस authenticateविधि में SessionAuthenticationकक्षा की विधि है :

self.enforce_csrf(request)

यदि आप CSRF चेक नहीं चाहते हैं तो आप Requestक्लास को संशोधित कर सकते हैं, जिसके पास एक संपत्ति है, जिसे आप csrf_exemptअपने संबंधित व्यू क्लास के अंदर रख सकते हैं और इसे इनिशियलाइज़ Trueकर सकते हैं। उदाहरण के लिए:

अगला, उपरोक्त कोड को निम्नानुसार संशोधित करें:

if not request.csrf_exempt:
    self.enforce_csrf(request)

कुछ संबंधित परिवर्तन आपको Requestकक्षा में करने होंगे। एक पूर्ण कार्यान्वयन यहाँ उपलब्ध है (पूर्ण विवरण के साथ): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7bad70dfd7ed


1

मेरा समाधान झटका दिखाया गया है। बस मेरी क्लास सजाओ।

from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(basic_auth_required(
    target_test=lambda request: not request.user.is_authenticated
), name='dispatch')
class GenPedigreeView(View):
    pass

1
हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन यह कोड इस और क्यों या कैसे का उत्तर देता है, इस संबंध में अतिरिक्त संदर्भ प्रदान करता है।
एलेक्स रिआबोव जूल

0

REST API POST का उपयोग करते समय, X-CSRFToken अनुरोध शीर्ष लेख की अनुपस्थिति उस त्रुटि का कारण हो सकती है। Django डॉक्स JS से CSRF टोकन मूल्य प्राप्त करने और सेट करने पर एक नमूना कोड प्रदान करता है।

जैसा कि ऊपर दिए गए जवाबों में कहा गया है, CSRF चेक तब होता है जब SessionAuthentication का उपयोग किया जाता है। एक अन्य दृष्टिकोण है टोकनएथुनेशन का उपयोग करना, लेकिन ध्यान रखें कि इसे REST_FRAMEWORK सेटिंग के DEFAULT_AUTHENTICATION_CLASSES की सूची में पहले स्थान पर रखा जाए।


-1

DNS रिबाइंडिंग अटैक के दौरान यह भी एक समस्या हो सकती है ।

DNS परिवर्तनों के बीच, यह एक कारक भी हो सकता है। जब तक DNS पूरी तरह से फ्लश नहीं हो जाता, तब तक यह इंतजार करना होगा कि यह DNS समस्याओं / परिवर्तनों से पहले काम कर रहा है या नहीं।


ऊपर के प्रश्न से यह क्या हो गया है?
नाविक

मतलब कि यह समस्या तब हो सकती है जब आप DNS को स्विच कर रहे हैं और यह पूरी तरह से प्रचारित नहीं हुआ है। यदि ऐप में Django के सामान्य सत्र की तुलना में अलग-अलग रूटिंग है, तो यही कारण है। बस एक किनारे मामले की सूचना मैं भाग गया। यह कुछ हद तक विहित संसाधन लगता है, इसलिए मैंने सोचा कि मैं एक अतिरिक्त संसाधन जोड़ूंगा।
फ्रिसिना
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.