Django Rest Framework eliminar csrf
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?
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 SessionAuthentication
esquema predeterminado utilizado por DRF. DRF SessionAuthentication
utiliza el marco de sesión de Django para la autenticación, lo que requiere que se verifique CSRF.
Cuando no define ninguna authentication_classes
en 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 DELETE
solicitudes.
¿Qué hacer entonces?
Ahora, para deshabilitar la verificación csrf, puede crear una clase de autenticación personalizada CsrfExemptSessionAuthentication
que se extienda desde la SessionAuthentication
clase 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_classes
como:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
Esto debería manejar el error csrf.
Solución más fácil:
En views.py, use django-braces' CsrfExemptMixin
y 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})
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!
Para todos los que no encontraron una respuesta útil. Sí, DRF elimina automáticamente la protección CSRF si no usa SessionAuthentication
AUTHENTICATION CLASS; por ejemplo, muchos desarrolladores usan solo JWT:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
Pero el problema CSRF not set
puede 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()),
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