web-dev-qa-db-fra.com

Django REST Framework CSRF Failed: Le cookie CSRF n'est pas défini

J'utilise l'infrastructure de repos Django pour effectuer des appels d'API via IOS et j'obtiens le message d'erreur suivant: "Échec de la CSRF: le cookie CSRF n'est pas défini".

Voici mon code API Django:

class LoginView(APIView):
    """
    List all snippets, or create a new snippet.
    """
    @csrf_exempt
    def get(self, request, format=None):
        startups = Startup.objects.all()
        serializer = StartupSerializer(startups, many=True)
        return Response(serializer.data)

    @csrf_exempt
    def post(self, request, format=None):
        profile = request.POST
....

Que puis-je faire?

17
user2237822

Si quelqu'un suit encore cette question, la réponse directe est que vous devez utiliser le décorateur sur la méthode d'affichage elle-même. Les méthodes get et post définies dans la classe APIView indiquent simplement à DRF le comportement de la vue réelle, mais la méthode de vue attendue par le routeur Django n'est pas instanciée tant que vous n'avez pas appelé LoginView.as_view().

Ainsi, la solution consiste à ajouter le décorateur csrf_exempt à urls.py. Cela pourrait ressembler à ceci:

#file: urls.py

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

import views

urlpatterns = patterns('',
    url('^login/$', csrf_exempt(views.LoginView.as_view())),
    ...
)

Toutefois, comme Mark l’a souligné ci-dessus, la protection des fichiers csr est importante pour éviter le piratage de vos sessions. Je n'ai pas travaillé avec iOS moi-même, mais je me pencherais sur l'utilisation des jetons csrf basés sur des cookies de Django . Vous pouvez utiliser le décorateur ensure_csrf_cookie pour que Django envoie un cookie csrftoken avec une réponse. Vos demandes POST seront validées tant que vous incluez ce jeton dans l'en-tête X-CSRFToken.

14

Le problème que vous rencontrez ici est que Django pour le traitement de votre vue utilise la méthode as_view() qui sera renvoyée, et non directement la méthode get() ou post().

Par conséquent, vous devez décorer votre vue basée sur les classes de l’une des manières suivantes:

  1. Dans urls.py
 urlpatterns = patterns ('', 
 url ('^ login/$', csrf_exempt (views.LoginView.as_view ())), 
 ... 
) 
  1. ou sur la méthode dispatch() (avant Django 1.9)
 de Django.utils.decorators import method_decorator 
 
 class LoginView (APIView): 
 @method_decorator (csrf_exempt) 
 def dispatch (self, * args, ** kwargs): 
 ... 
  1. ou sur la vue de classe elle-même (à partir de Django 1.9)
 de Django.utils.decorators import method_decorator 
 
 
 @method_decorator (csrf_exempt, name = 'dispatch') 
 class LoginView (APIView): 
 ... 
3
thedk

Pour les GET, vous ne devriez pas modifier les données, vous n'avez donc pas besoin d'un CSRF.

Si vous modifiez des données avec un POST, vous DEVRIEZ avoir un CSRF si vous utilisez une authentification basée sur une session. Sinon, vous ouvrez un trou de sécurité. Même si vous pensez que votre serveur Django desservira les applications iPhone, rien n'empêche une personne possédant votre application de détecter les paquets sur le trafic acheminé vers votre serveur, puis de procéder à une ingénierie inverse de l'accès au serveur avec d'autres types de clients Web. Pour cette raison, Django Rest Framework nécessite un CSRF dans certains cas. Ceci est mentionné dans la documentation du framework de repos Django .

Le chemin autour de cette exigence pour les POST consiste à ne pas utiliser l'authentification de session. Par exemple, vous pouvez utiliser BasicAuthentication sur HTTPS. Avec ce mécanisme d'authentification, vous devez utiliser HTTPS pour empêcher les identifiants d'être transmis en clair avec chaque demande.

2
Mark Chackerian

J'ai eu le même problème. Mon problème était que j'ai oublié de mettre .as_view() dans urls.py sur MyAPIView. Donc ça doit être comme:

url(r'$', GetLikesAPI.as_view(), name='list')

ne pas:

url(r'$', GetLikesAPI, name='list')
2
М.Б.

Dans mon cas, c’est parce que j’ai envoyé la demande de mise à url = ' http://example.com/list/5 ' sans barre oblique à la fin. Quand j'ai changé d'url en url = ' http://example.com/list/5/ ', tout a commencé à fonctionner.

1
Radren

C'est une vieille question mais quelque chose que nous avons rencontré récemment.

DRF désactive CSRF par défaut, à moins d'utiliser l'authentification de session. Par défaut, NSURLconnection est configuré pour gérer les cookies. Vous devez indiquer explicitement à l'application iOS de ne pas utiliser de cookies. Ensuite, vous pouvez continuer à utiliser l'authentification de session si nécessaire et ne pas avoir à csrf exempter vos vues.

0
kevswanberg
urlpatterns = patterns('',
       url('^login/$', csrf_exempt(views.LoginView.as_view())),
       ...
)

Les mecs. J'ai eu la même erreur et passé beaucoup de temps rien que pour constater que: 1) j'avais un autre routeur avec 'login' et là j'ai raté '$'. Je veux dire parfois que vous pouvez oublier quelque chose dans le routage et obtenir cette erreur.

0
Df.fpm