Django Rest Framework remove csrf

Eu sei que existem respostas sobre o Django Rest Framework, mas não consegui encontrar uma solução para o meu problema.

Eu tenho um aplicativo que possui autenticação e alguma funcionalidade. Eu adicionei um novo aplicativo para ele, que usa o Django Rest Framework. Eu quero usar a biblioteca somente neste aplicativo. Também quero fazer uma solicitação POST e sempre recebo essa resposta:

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

Eu tenho o seguinte 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}) 

Eu quero adicionar a API sem afetar o aplicativo atual. Então, minhas perguntas são como posso desabilitar o CSRF somente para este aplicativo?

Por que esse erro está acontecendo?

Isso está acontecendo devido ao esquema SessionAuthentication padrão usado pelo DRF. A SessionAuthentication de DRF usa a estrutura de session do Django para autenticação que requer que o CSRF seja verificado.

Quando você não define any authentication_classs em sua view / viewset, o DRF usa essas classs de autenticação como padrão.

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

Como o DRF precisa suportar autenticação baseada em session e não em session para as mesmas visualizações, ele impõe a verificação de CSRF somente para usuários autenticados. Isso significa que somente solicitações autenticadas exigem tokens de CSRF e solicitações anônimas podem ser enviadas sem tokens de CSRF.

Se você estiver usando uma API de estilo AJAX com SessionAuthentication, precisará include um token CSRF válido para todas as chamadas de método HTTP “inseguras”, como as solicitações PUT, PATCH, POST or DELETE .

O que fazer então?

Agora, para desabilitar a verificação do csrf, você pode criar uma class de autenticação personalizada CsrfExemptSessionAuthentication que se estende da class SessionAuthentication padrão. Nessa class de autenticação, replaceemos a verificação enforce_csrf() que estava acontecendo dentro da SessionAuthentication real.

 from rest_framework.authentication import SessionAuthentication, BasicAuthentication class CsrfExemptSessionAuthentication(SessionAuthentication): def enforce_csrf(self, request): return # To not perform the csrf check previously happening 

Na sua opinião, você pode definir as authentication_classs como:

 authentication_classs = (CsrfExemptSessionAuthentication, BasicAuthentication) 

Isso deve manipular o erro csrf.

Solução mais fácil:

Em views.py, use as chaves CsrfExemptMixin e authentication_classs:

 # 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_classs = [] def post(self, request, format=None): return Response({'received data': request.data}) 

Se você não quiser usar a autenticação baseada em session, poderá remover a Session Authentication de REST_AUTHENTICATION_CLASSES e isso removerá automaticamente todos os problemas com base em csrf. Mas nesse caso, as apis navegáveis ​​podem não funcionar.

Além deste erro não deve vir mesmo com a autenticação de session. Você deve usar autenticação customizada como TokenAuthentication para suas apis e certifique-se de enviar Accept:application/json e Content-Type:application/json (desde que você esteja usando o json) em suas solicitações junto com o token de autenticação.

Para todos que não encontraram uma resposta útil. Sim, o DRF remove automaticamente a proteção do CSRF se você não usar o SessionAuthentication AUTHENTICATION CLASS, por exemplo, muitos desenvolvedores usam apenas o JWT:

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

Mas a questão CSRF not set pode ter ocorrido a partir de algum outro motivo, por exemplo, você não adicionou corretamente o caminho para você ver:

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

ao invés de

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

Estou impressionado com o mesmo problema. Eu segui esta referência e funcionou. Solução é criar um middleware

Adicione o arquivo disable.py em um dos seus aplicativos (no meu caso é ‘myapp’)

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

E adicione o middileware às MIDDLEWARE_CLASSES

 MIDDLEWARE_CLASSES = ( myapp.disable.DisableCSRF, ) 

Modificar urls.py

Se você gerencia suas rotas em urls.py, pode agrupar as rotas desejadas com csrf_exempt () para excluí-las do middleware de verificação CSRF.

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

Alternativamente, como decorador, alguns podem achar o uso do decorador @csrf_exempt mais adequado às suas necessidades.

por exemplo,

 from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse @csrf_exempt def my_view(request): return HttpResponse('Hello world') 

deve começar o trabalho feito!

Se você estiver usando um ambiente virtual exclusivo para seu aplicativo, poderá usar a seguinte abordagem sem qualquer outro aplicativo.

O que você observou acontece porque o rest_framework/authentication.py possui este código no método authenticate da class SessionAuthentication :

 self.enforce_csrf(request) 

Você pode modificar a class Request para ter uma propriedade chamada csrf_exempt e inicializá-la dentro de sua respectiva class View para True se não quiser verificações de CSRF. Por exemplo:

Em seguida, modifique o código acima da seguinte maneira:

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

Existem algumas alterações relacionadas que você teria que fazer na class Request . Uma implementação completa está disponível aqui (com descrição completa): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7ed

Minha solução é mostrada golpe. Apenas decore minha aula.

 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