Django Rest Framework eliminar csrf

Resuelto Irene Texas asked hace 9 años • 17 respuestas

Sé que hay respuestas sobre Django Rest Framework, pero no pude encontrar una solución a mi problema.

Tengo una aplicación que tiene autenticación y algunas funciones. Le agregué una nueva aplicación, que usa Django Rest Framework. Quiero usar la biblioteca solo en esta aplicación. También quiero realizar una solicitud POST y siempre recibo esta respuesta:

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

Tengo el siguiente código:

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

Quiero agregar la API sin afectar la aplicación actual. Entonces mi pregunta es ¿cómo puedo desactivar CSRF solo para esta aplicación?

Irene Texas avatar Jun 16 '15 21:06 Irene Texas
Aceptado

Nota: Deshabilitar CSRF no es seguro desde el punto de vista de la seguridad. Utilice su criterio para utilizar el método siguiente.

¿Por qué ocurre este error?

Esto sucede debido al SessionAuthenticationesquema predeterminado utilizado por DRF. DRF SessionAuthenticationutiliza el marco de sesión de Django para la autenticación, lo que requiere que se verifique CSRF.

Cuando no define ninguna authentication_classesen su vista/conjunto de vistas, DRF usa estas clases de autenticación como predeterminadas.

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

Dado que DRF necesita admitir autenticación basada en sesión y no basada en sesión en las mismas vistas, aplica la verificación CSRF solo para usuarios autenticados. Esto significa que solo las solicitudes autenticadas requieren tokens CSRF y las solicitudes anónimas se pueden enviar sin tokens CSRF.

Si está utilizando una API de estilo AJAX con SessionAuthentication, deberá incluir un token CSRF válido para cualquier llamada a método HTTP "inseguro", como las PUT, PATCH, POST or DELETEsolicitudes.

¿Qué hacer entonces?

Ahora, para deshabilitar la verificación csrf, puede crear una clase de autenticación personalizada CsrfExemptSessionAuthenticationque se extienda desde la SessionAuthenticationclase predeterminada. En esta clase de autenticación, anularemos la enforce_csrf()verificación que estaba ocurriendo dentro del archivo 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

En su opinión, entonces puede definirlo authentication_classescomo:

authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

Esto debería manejar el error csrf.

Rahul Gupta avatar Jun 16 '2015 18:06 Rahul Gupta

Solución más fácil:

En views.py, use django-braces' CsrfExemptMixiny 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})
bixente57 avatar Dec 16 '2015 15:12 bixente57

Modificar URL.py

Si administra sus rutas en urls.py, puede ajustar las rutas que desee con csrf_exempt() para excluirlas del middleware de verificación CSRF.

import views

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


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

Alternativamente, como decorador, algunos pueden encontrar el uso del decorador @csrf_exempt más adecuado para sus necesidades.

por ejemplo,

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

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

¡Debería hacer el trabajo!

Syed Faizan avatar Aug 02 '2018 17:08 Syed Faizan

Para todos los que no encontraron una respuesta útil. Sí, DRF elimina automáticamente la protección CSRF si no usa SessionAuthenticationAUTHENTICATION CLASS; por ejemplo, muchos desarrolladores usan solo JWT:

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

Pero el problema CSRF not setpuede deberse a algún otro motivo, por ejemplo, no agregó correctamente la ruta a su vista:

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

en lugar de

url(r'^api/signup/', CreateUserView.as_view()),
Ivan Borshchov avatar Apr 01 '2017 14:04 Ivan Borshchov

Probé algunas de las respuestas anteriores y sentí que crear una clase separada era un poco exagerado.

Como referencia, me encontré con este problema al intentar actualizar un método de vista basado en funciones a un método de vista basado en clases para el registro de usuarios.

Cuando utilice vistas basadas en clases (CBV) y Django Rest Framework (DRF), herede de la clase ApiView y establezca permiso_clases y autenticación_clases en una tupla vacía. Encuentre un ejemplo a continuación.

class UserRegistrationView(APIView):

    permission_classes = ()
    authentication_classes = ()

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

        # rest of your code here
Mike Hawes avatar Mar 15 '2019 03:03 Mike Hawes