Sé que hay respuestas con respecto a 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 hacer 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 deshabilitar CSRF solo para esta aplicación?
django
django-rest-framework
csrf
django-csrf
Irene Texas
fuente
fuente
Respuestas:
¿Por qué ocurre este error?
Esto sucede debido al
SessionAuthentication
esquema predeterminado utilizado por DRF. DRFSessionAuthentication
usa el marco de sesión de Django para la autenticación, 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 las predeterminadas.Dado que DRF necesita admitir autenticación basada en sesión y no sesión para 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 pueden enviarse sin tokens CSRF.
Si está utilizando una API de estilo AJAX con SessionAuthentication, deberá incluir un token CSRF válido para cualquier llamada de método HTTP "insegura", 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 laSessionAuthentication
clase predeterminada . En esta clase de autenticación, anularemos laenforce_csrf()
verificación que estaba sucediendo dentro del archivo realSessionAuthentication
.En su opinión, puede definir
authentication_classes
que sea:Esto debería manejar el error csrf.
fuente
Solución más sencilla:
En views.py, use llaves CsrfExemptMixin y authentication_classes:
fuente
Modificar urls.py
Si administra sus rutas en urls.py, puede envolver sus rutas deseadas con csrf_exempt () para excluirlas del middleware de verificación CSRF.
Alternativamente, como decorador, algunos pueden encontrar el uso del decorador @csrf_exempt más adecuado para sus necesidades
por ejemplo,
debe hacer el trabajo!
fuente
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 solo usan JWT:Pero el problema
CSRF not set
puede ocurrir por alguna otra razón, por ejemplo, no agregó correctamente la ruta a su vista:en vez de
fuente
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 las clases de permiso y las clases de autenticación en una tupla vacía. Encuentre un ejemplo a continuación.
fuente
Si no desea utilizar la autenticación basada en sesión, puede eliminar
Session Authentication
de REST_AUTHENTICATION_CLASSES y eso eliminaría automáticamente todos los problemas basados en csrf. Pero en ese caso, las apis navegables podrían no funcionar.Además, este error no debería venir ni siquiera con la autenticación de sesión. Debe usar autenticación personalizada como TokenAuthentication para sus apis y asegúrese de enviar
Accept:application/json
yContent-Type:application/json
(siempre que esté usando json) en sus solicitudes junto con el token de autenticación.fuente
Debe agregar esto para evitar la autenticación de sesión predeterminada: (settings.py)
Entonces: (views.py)
fuente
Me golpea el mismo problema. Seguí esta referencia y funcionó. La solución es crear un middleware
Agregue el archivo disable.py en una de sus aplicaciones (en mi caso es 'myapp')
Y agregue el middileware a MIDDLEWARE_CLASSES
fuente
Si está utilizando un entorno virtual exclusivo para su aplicación, puede utilizar el siguiente enfoque sin ninguna otra aplicación efectiva.
Lo que observaste sucede porque
rest_framework/authentication.py
tiene este código en elauthenticate
método deSessionAuthentication
clase:Puede modificar la
Request
clase para tener una propiedad llamadacsrf_exempt
e inicializarla dentro de su respectiva clase de VistaTrue
si no desea verificaciones CSRF. Por ejemplo:A continuación, modifique el código anterior de la siguiente manera:
Hay algunos cambios relacionados que tendrías que hacer en la
Request
clase. Una implementación completa está disponible aquí (con una descripción completa): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7edfuente
Mi solución se muestra golpe. Solo decora mi clase.
fuente
Cuando se utilizan POST de la API REST, la ausencia del encabezado de solicitud X-CSRFToken puede causar ese error. Los documentos de Django proporcionan un código de muestra para obtener y configurar el valor del token CSRF de JS.
Como se señaló en las respuestas anteriores, la verificación CSRF ocurre cuando se usa SessionAuthentication. Otro enfoque es usar TokenAuthentication, pero tenga en cuenta que debe colocarse primero en la lista de DEFAULT_AUTHENTICATION_CLASSES de la configuración REST_FRAMEWORK.
fuente
Esto también podría ser un problema durante un ataque de reversión de DNS .
Entre los cambios de DNS, esto también puede ser un factor. Esperar hasta que el DNS se vacíe por completo resolverá esto si estaba funcionando antes de los problemas / cambios de DNS.
fuente