it-swarm.com.de

Django Rest Framework csrf entfernen

Ich weiß, dass es Antworten zu Django Rest Framework gibt, aber ich konnte keine Lösung für mein Problem finden.

Ich habe eine Anwendung, die Authentifizierung und einige Funktionen hat. Ich habe eine neue App hinzugefügt, die Django Rest Framework verwendet. Ich möchte die Bibliothek nur in dieser App verwenden. Ich möchte auch POST anfordern und ich erhalte immer diese Antwort:

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

Ich habe folgenden Code:

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

Ich möchte die API hinzufügen, ohne die aktuelle Anwendung zu beeinträchtigen. Meine Frage ist also, wie ich CSRF nur für diese App deaktivieren kann.

89
Irene Texas

Warum tritt dieser Fehler auf?

Dies geschieht aufgrund des von DRF verwendeten Standardschemas SessionAuthentication. DRFs SessionAuthentication verwendet das Django-Session-Framework für die Authentifizierung, bei der die CSRF überprüft werden muss.

Wenn Sie in Ihrer Ansicht/Ihrem Viewset kein authentication_classes Definieren, verwendet DRF diese Authentifizierungsklassen als Standard.

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

Da DRF sowohl die sitzungsbasierte als auch die nicht sitzungsbasierte Authentifizierung für dieselben Ansichten unterstützen muss, wird die CSRF-Prüfung nur für authentifizierte Benutzer erzwungen. Dies bedeutet, dass nur authentifizierte Anforderungen CSRF-Token erfordern und anonyme Anforderungen möglicherweise ohne CSRF-Token gesendet werden.

Wenn Sie eine API im AJAX Stil mit SessionAuthentication verwenden, müssen Sie ein gültiges CSRF-Token für alle "unsicheren" HTTP-Methodenaufrufe wie PUT, PATCH, POST or DELETE - Anforderungen einschließen.

Was ist dann zu tun?

Jetzt können Sie die CSRF-Prüfung deaktivieren, indem Sie eine benutzerdefinierte Authentifizierungsklasse CsrfExemptSessionAuthentication erstellen, die von der Standardklasse SessionAuthentication abweicht. In dieser Authentifizierungsklasse überschreiben wir die enforce_csrf() -Prüfung, die innerhalb des tatsächlichen SessionAuthentication stattgefunden hat.

from rest_framework.authentication import SessionAuthentication, BasicAuthentication 

class CsrfExemptSessionAuthentication(SessionAuthentication):

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

Aus Ihrer Sicht können Sie den authentication_classes Folgendermaßen definieren:

authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

Dies sollte den csrf-Fehler behandeln.

185
Rahul Gupta

Einfachere Lösung:

Verwenden Sie in views.py die geschweiften Klammern CsrfExemptMixin und authentication_classes:

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

Ändern Sie urls.py

Wenn Sie Ihre Routen in urls.py verwalten, können Sie Ihre gewünschten Routen mit csrf_exempt () umbrechen, um sie von der CSRF-Überprüfungs-Middleware auszuschließen.

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())),
    ...
)

Alternativ können Sie als Dekorateur die Verwendung des Dekorateurs @csrf_exempt für Ihre Anforderungen besser geeignet finden

zum Beispiel,

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

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

sollte den Job erledigen!

11
Syed Faizan

Wenn Sie keine sitzungsbasierte Authentifizierung verwenden möchten, können Sie Session Authentication Aus REST_AUTHENTICATION_CLASSES entfernen. Dadurch werden automatisch alle auf csrf basierenden Probleme entfernt. In diesem Fall funktionieren Browseable-APIs möglicherweise nicht.

Außerdem sollte dieser Fehler auch bei der Sitzungsauthentifizierung nicht auftreten. Sie sollten eine benutzerdefinierte Authentifizierung wie TokenAuthentication für Ihre API verwenden und sicherstellen, dass Sie in Ihren Anforderungen Accept:application/json Und Content-Type:application/json (Vorausgesetzt, Sie verwenden JSON) zusammen mit dem Authentifizierungstoken senden.

8
hspandher

Für alle, die keine hilfreiche Antwort gefunden haben. Ja DRF entfernt automatisch den CSRF-Schutz, wenn Sie SessionAuthentication AUTHENTICATION CLASS nicht verwenden. Viele Entwickler verwenden beispielsweise nur JWT:

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

Aber Problem CSRF not set kann aus einem anderen Grund auftreten, z. B. weil Sie den Pfad Ihrer Ansicht nicht korrekt hinzugefügt haben:

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

anstatt

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

Ich bin mit dem gleichen Problem betroffen. Ich folgte diesem Hinweis und es hat funktioniert. Die Lösung besteht darin, eine Middleware zu erstellen

Füge disable.py in eine deiner Apps ein (in meinem Fall ist es 'myapp')

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

Und fügen Sie die Middileware zu den MIDDLEWARE_CLASSES hinzu

MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
3
Venkatesh Mondi

Ich habe ein paar der obigen Antworten ausprobiert und fand, dass es ein wenig übertrieben war, eine eigene Klasse zu gründen.

Als Referenz bin ich auf dieses Problem gestoßen, als ich versuchte, eine funktionsbasierte Ansichtsmethode auf eine klassenbasierte Ansichtsmethode für die Benutzerregistrierung zu aktualisieren.

Wenn Sie klassenbasierte Ansichten (CBVs) und Django Rest Framework (DRF)) verwenden, erben Sie von der ApiView-Klasse und setzen die permission_classes und authentication_classes auf ein leeres Tuple.

class UserRegistrationView(APIView):

    permission_classes = ()
    authentication_classes = ()

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

        # rest of your code here
2
Mike Hawes

Wenn Sie für Ihre Anwendung eine exklusive virtuelle Umgebung verwenden, können Sie den folgenden Ansatz verwenden, ohne andere Anwendungen zu aktivieren.

Was Sie beobachtet haben, passiert, weil rest_framework/authentication.py Diesen Code in der authenticate -Methode der SessionAuthentication -Klasse hat:

self.enforce_csrf(request)

Sie können die Klasse Request so ändern, dass sie eine Eigenschaft mit dem Namen csrf_exempt Hat, und sie in Ihrer jeweiligen View-Klasse mit True initialisieren, wenn Sie keine CSRF-Prüfungen wünschen. Beispielsweise:

Ändern Sie als Nächstes den obigen Code wie folgt:

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

Es gibt einige verwandte Änderungen, die Sie in der Klasse Request vornehmen müssen. Eine vollständige Implementierung finden Sie hier (mit vollständiger Beschreibung): https://github.com/piaxis/Django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7ed

1
Reetesh Ranjan

Meine Lösung wird Schlag gezeigt. Schmücke einfach meine Klasse.

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
Jak Liao