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?
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
.
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:
urlpatterns = patterns ('', url ('^ login/$', csrf_exempt (views.LoginView.as_view ())), ... )
dispatch()
(avant Django 1.9)de Django.utils.decorators import method_decorator class LoginView (APIView): @method_decorator (csrf_exempt) def dispatch (self, * args, ** kwargs): ...
de Django.utils.decorators import method_decorator @method_decorator (csrf_exempt, name = 'dispatch') class LoginView (APIView): ...
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.
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')
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.
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.
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.