Django jeton csrf + Angularjs

j'ai django tournant sur un serveur apache utilisant mod_wsgi, ainsi qu'une application angularjs servie directement par apache, pas par django. J'aimerais faire des appels postaux vers le serveur django (exécutant rest_fram Framework) mais j'ai des problèmes avec le jeton csrf.

y a-t-il un moyen de configurer le token depuis le serveur sans mettre {% csrf token %} dans le modèle (puisque ces pages ne passent pas par django)?

  1. je comme pouvoir obtenir un jeton csrf à travers une requête GET en cookie.
  2. je voudrais pouvoir ensuite faire des requêtes POST vers le serveur django avec la valeur du cookie de token csrf.
62
demandé sur Hieu Nguyen 2013-08-10 02:13:28

5 réponses

Django et AngularJS ont déjà le soutien du CSRF, votre rôle est assez simple.

tout D'abord, vous devez activer CSRF à Django, je crois que vous l'avez déjà fait, sinon, suivre Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax .

maintenant, Django va configurer un cookie nommé csrftoken sur la première requête GET et s'attend à un en-tête HTTP personnalisé X-CSRFToken sur les requêtes POST/PUT/DELETE ultérieures.

pour Angular, il attend le cookie nommé XSRF-TOKEN et fera des requêtes POST/PUT/DELETE avec X-XSRF-TOKEN en-tête, donc vous avez besoin de faire un peu de tweak pour faire les deux aller avec l'autre:

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

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

C'est ça.

NOTE: ceci est pour l'angle 1.1.5, versions plus anciennes pourriez avoir besoin d'une approche différente.

mise à jour:

étant donné que l'application angular app n'est pas desservie par django, afin de laisser le cookie être réglé, angular app doit d'abord faire une requête GET à django.

106
répondu Ye Liu 2013-08-09 23:05:48
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 est utilisé, enverront des requêtes avec un jeton csrf.

59
répondu Nikolay Baluk 2015-01-26 16:31:32

après avoir cherché autour, ce qui a fonctionné pour moi était de ce post 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');
})

c'est bien entendu après avoir reçu le cookie par le biais d'une requête GET du serveur django.

j'ai aussi examiné quelques-unes des autres réponses ici, y compris celle de Ye Liun mais je n'ai rien trouvé dans les docs officiels spécifiant des modifications aux options par défaut pour xsrf sur $httpProvider, autre que cette demande de tirage qui ne fonctionnait pas pour moi au moment où j'ai écrit ce post.

11
répondu Preom 2015-11-30 14:10:10

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 l'index.fichier html (qui est juste un sym.lien.) De cette façon, le Cookie CSRF est défini sans requête GET supplémentaire.

Please see my answer here about AngularJS Single Page Web Application on Sub-domain a talking to a Django JSON (REST) API on Sub-domain B using CORS and CSRF protection

1
répondu Visionscaper 2017-05-23 11:47:31

si vous avez défini 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 requête. Il ne change que lorsque un utilisateur se connecte. Si vous faites une application simple page angulaire, vous devez vous assurer que vous réinitialisez le token sur connexion/déconnexion et cela devrait fonctionner.

NOTE: cela ne fonctionne pas actuellement dans Django 1.10 ou plus tard en raison du changement de jeton CSRF sur chaque demande. Voir Pass Django CSRF token to Angular with CSRF_COOKIE_HTTPONLY

0
répondu Zags 2017-05-23 12:02:59