Django csrf token + Angularjs

J'ai installé django sur un serveur apache en utilisant mod_wsgi, ainsi qu'une application angularjs directement fournie par apache, pas par django. J'aimerais faire des appels POST au serveur django (en cours de repos_framework) mais j'ai des problèmes avec le jeton csrf.

Est-il possible de définir le jeton du serveur sans mettre {% csrf token %} dans le cadre du modèle (puisque ces pages ne transitent pas par django)?

  1. Je voudrais pouvoir obtenir un jeton csrf via une requête GET en tant que cookie.
  2. Je voudrais pouvoir ensuite faire des demandes POST au serveur django avec la valeur cookie csrf token.

Django et AngularJS ont tous deux un support CSRF déjà, votre part est assez simple.

Tout d'abord, vous devez activer CSRF dans Django, je crois que vous l'avez déjà fait, sinon, suivez le document Django https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax .

Maintenant, Django définira un cookie nommé csrftoken lors de la première requête GET et attend un en-tête HTTP personnalisé X-CSRFToken sur les X-CSRFToken POST / PUT / DELETE ultérieures.

Pour Angular, il s'attend à ce que le cookie nommé XSRF-TOKEN et effectue des requêtes POST / PUT / DELETE avec l'en X-XSRF-TOKEN , donc vous devez faire un peu de tord pour faire avancer les deux entre eux:

 $httpProvider.defaults.xsrfCookieName = 'csrftoken'; $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 

Ajoutez au-dessus de deux lignes quelque part dans votre code js, le bloc module.config () est un bon endroit pour cela.

C'est tout.

REMARQUE: ceci est pour le 1.1.5 angulaire, les anciennes versions peuvent nécessiter une approche différente.

Mettre à jour:

Étant donné que l'application angulaire n'est pas desservie par django, afin de laisser configurer le cookie, l'application angulaire doit d'abord faire une requête GET à django.

 var foo = angular.module('foo', ['bar']); foo.config(['$httpProvider', function($httpProvider) { $httpProvider.defaults.xsrfCookieName = 'csrftoken'; $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; }]); 

Et tous les services et contrôleurs de modules, où $ http utilisé, enverront des requêtes avec un jeton csrf.

Après avoir parcouru la recherche, ce qui a fonctionné pour moi provient de cette publication avec le code suivant:

 angular.module( '[your module name]', ... [some dependencies] ... 'ngCookies', ... [other dependencies] ... ) .run( function run( $http, $cookies ){ // For CSRF token compatibility with Django $http.defaults.headers.post['X-CSRFToken'] = $cookies.get('csrftoken'); }) 

Bien sûr, après avoir obtenu le cookie grâce à une demande GET du serveur django.

J'ai également examiné certaines des autres réponses ici, y compris Ye Liun, mais je n'ai rien trouvé dans les documents officiels spécifiant les modifications apportées aux options par défaut pour xsrf sur $ httpProvider, à part cette demande de tirage qui ne m'a pas fonctionné à la Fois que j'écris cette publication.

J'ai créé une application Django pour mon application AngularJS, dans le même projet Django que mon application (REST) ​​API Django, qui ne sert que le fichier index.html (qui est juste un sym.link). De cette façon, le cookie CSRF est défini sans requête GET supplémentaire.

Veuillez consulter ma réponse ici sur l' application Web AngularJS Single Page sur le sous-domaine A qui parle d'une API Django JSON (REST) ​​sur le sous-domaine B en utilisant la protection CORS et CSRF

Si vous avez configuré vos cookies pour interdire l'accès javascript, vous devez faire ce qui suit. Dans votre modèle, avant de créer l'application django, ajoutez ceci:

 <script> window.csrf_token = "{{ csrf_token }}"; </script> 

Dans votre application angulaire, ajoutez ceci:

 angularApp.config(["$httpProvider", function($httpProvider) { $httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token; }]); 

Au moins par Django 1.9, le jeton CSRF ne change pas avec chaque demande. Il ne change que lorsqu'un utilisateur se connecte. Si vous effectuez une application angulaire à une seule page, vous devez vous assurer de réinitialiser le jeton lors de la connexion / connexion et cela devrait fonctionner correctement.

REMARQUE: cela ne fonctionne pas actuellement dans Django 1.10 ou plus tard en raison de la modification du jeton CSRF sur chaque demande. Voir Pass Django CSRF token à Angular avec CSRF_COOKIE_HTTPONLY