Eu sei que existem respostas sobre Django Rest Framework, mas não consegui encontrar uma solução para o meu problema.
Tenho um aplicativo que possui autenticação e algumas funcionalidades. Eu adicionei um novo aplicativo a ele, que usa Django Rest Framework. Quero usar a biblioteca apenas neste aplicativo. Também quero fazer uma solicitação POST e sempre recebo esta 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})
Quero adicionar a API sem afetar o aplicativo atual. Então, minha dúvida é como posso desativar o CSRF apenas para este aplicativo?
django
django-rest-framework
csrf
django-csrf
Irene Texas
fonte
fonte
Respostas:
Por que esse erro está acontecendo?
Isso está acontecendo por causa do
SessionAuthentication
esquema padrão usado pelo DRF. O DRFSessionAuthentication
usa a estrutura de sessão do Django para autenticação que requer que o CSRF seja verificado.Quando você não define nenhum
authentication_classes
em seu view / viewset, o DRF usa essas classes de autenticação como o padrão.Como o DRF precisa oferecer suporte à autenticação baseada em sessão e não-sessão para as mesmas visualizações, ele impõe a verificação CSRF apenas para usuários autenticados. Isso significa que apenas solicitações autenticadas requerem tokens CSRF e solicitações anônimas podem ser enviadas sem tokens CSRF.
Se estiver usando uma API de estilo AJAX com SessionAuthentication, você precisará incluir um token CSRF válido para todas as chamadas de método HTTP "não seguras", como
PUT, PATCH, POST or DELETE
solicitações.O que fazer então?
Agora, para desabilitar a verificação csrf, você pode criar uma classe de autenticação personalizada
CsrfExemptSessionAuthentication
que se estende daSessionAuthentication
classe padrão . Nesta classe de autenticação, iremos substituir aenforce_csrf()
verificação que estava acontecendo dentro do realSessionAuthentication
.Em sua opinião, você pode definir o
authentication_classes
como:Isso deve lidar com o erro csrf.
fonte
Solução mais fácil:
Em views.py, use as chaves CsrfExemptMixin e authentication_classes:
fonte
Modificar urls.py
Se você gerencia suas rotas em urls.py, pode agrupar suas rotas desejadas com csrf_exempt () para excluí-las do middleware de verificação CSRF.
Como alternativa, como decorador, alguns podem achar o uso do decorador @csrf_exempt mais adequado para suas necessidades
por exemplo,
deve fazer o trabalho!
fonte
Para todos os que não encontraram uma resposta útil. Sim, o DRF remove automaticamente a proteção CSRF se você não usar a
SessionAuthentication
AUTHENTICATION CLASS, por exemplo, muitos desenvolvedores usam apenas JWT:Mas o problema
CSRF not set
pode ter ocorrido por algum outro motivo, por exemplo, você não adicionou corretamente o caminho para sua visualização:ao invés de
fonte
Tentei algumas das respostas acima e senti que criar uma classe separada era um pouco exagero.
Para referência, encontrei este problema ao tentar atualizar um método de visualização baseado em função para um método de visualização baseado em classe para registro de usuário.
Ao usar visões baseadas em classes (CBVs) e Django Rest Framework (DRF), herde da classe ApiView e defina permission_classes e authentication_classes como uma tupla vazia. Encontre um exemplo abaixo.
fonte
Se você não quiser usar autenticação baseada em sessão, você pode remover
Session Authentication
de REST_AUTHENTICATION_CLASSES e isso removeria automaticamente todos os problemas baseados em csrf. Mas, nesse caso, as apis navegáveis podem não funcionar.Além disso, este erro não deve vir mesmo com autenticação de sessão. Você deve usar autenticação personalizada como TokenAuthentication para seu apis e certifique-se de enviar
Accept:application/json
eContent-Type:application/json
(desde que você esteja usando json) em suas solicitações junto com o token de autenticação.fonte
Você precisa adicionar isso para evitar a autenticação de sessão padrão: (settings.py)
Então: (views.py)
fonte
Estou impressionado com o mesmo problema. Segui essa referência e funcionou. A solução é criar um middleware
Adicione o arquivo disable.py em um de seus aplicativos (no meu caso, é 'myapp')
E adicione o middileware ao MIDDLEWARE_CLASSES
fonte
Se estiver usando um ambiente virtual exclusivo para seu aplicativo, você pode usar a abordagem a seguir sem efetivar nenhum outro aplicativo.
O que você observou acontece porque
rest_framework/authentication.py
tem este código noauthenticate
método daSessionAuthentication
classe:Você pode modificar a
Request
classe para ter uma propriedade chamadacsrf_exempt
e inicializá-la dentro de sua respectiva classe de visualizaçãoTrue
se não quiser verificações CSRF. Por exemplo:Em seguida, modifique o código acima da seguinte maneira:
Existem algumas mudanças relacionadas que você teria que fazer na
Request
aula. Uma implementação completa está disponível aqui (com a descrição completa): https://github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7edfonte
Minha solução é mostrada golpe. Apenas decore minha classe.
fonte
Ao usar POSTs da API REST, a ausência do cabeçalho de solicitação X-CSRFToken pode causar esse erro. Os documentos do Django fornecem um código de amostra para obter e configurar o valor do token CSRF do JS.
Conforme apontado nas respostas acima, a verificação CSRF ocorre quando o SessionAuthentication é usado. Outra abordagem é usar TokenAuthentication, mas lembre-se de que ele deve ser colocado primeiro na lista de DEFAULT_AUTHENTICATION_CLASSES da configuração REST_FRAMEWORK.
fonte
Isso também pode ser um problema durante um ataque DNS Rebinding .
Entre as mudanças de DNS, isso também pode ser um fator. Esperar até que o DNS seja totalmente liberado resolverá isso se ele estava funcionando antes de problemas / alterações de DNS.
fonte