Question Comment créer une requête POST (y compris un jeton CSRF) en utilisant Django et AngularJS


J'essaie de créer une requête POST en utilisant angular.js dans cette vue Django.

class PostJSON4SlickGrid(View):
    """
    REST POST Interface for SlickGrid to update workpackages
    """

    def post(self, request, root_id, wp_id, **kwargs):
        print "in PostJSON4SlickGrid"
        print request.POST
        return HttpResponse(status=200)

J'ai donc créé cette ressource.

myModule.factory('gridData', function($resource) {
    //define resource class
    var root = {{ root.pk }};
    return $resource('{% url getJSON4SlickGrid root.pk %}:wpID/', {wpID:'@id'},{
            get: {method:'GET', params:{}, isArray:true},
            update:{method:'POST'}
    });
});

Appeler le obtenir méthode dans un contrôleur fonctionne très bien. L'URL se traduit par http://127.0.0.1:8000/pm/rest/tree/1/.

function gridController($scope, gridData){
    gridData.get(function(result) {
        console.log(result);
        $scope.treeData = result;
        //broadcast that asynchronous xhr call finished
        $scope.$broadcast('mySignal', {fake: 'Hello!'});  
    });
}

Alors que je suis confronté à des problèmes d’exécution de la méthode update / POST.

item.$update();

L'URL est traduite en http://127.0.0.1:8000/pm/rest/tree/1/345, qui manque une barre oblique. Cela peut être facilement contourné lorsque vous n'utilisez pas une barre oblique dans votre définition d'URL.

url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'),

au lieu de

url(r'^rest/tree/(?P<root_id>\d+)/(?P<wp_id>\d+)/$', PostJSON4SlickGrid.as_view(), name='postJSON4SlickGrid'),

En utilisant la solution de contournement sans le slash final, je reçois maintenant un code de statut 403 (Forbidden), probablement dû au fait que je ne passe pas un CSRF jeton dans la requête POST. Par conséquent, ma question se résume à la façon dont je peux passer le jeton CSRF dans la requête POST créée par angulaire?

Je connais ce approche pour passer le jeton csrf via les en-têtes, mais je cherche une possibilité de ajouter le jeton au corps de la demande de publicationcomme suggéré ici. Est-il possible en angulaire d'ajouter des données au corps de la requête postérieure?

En tant que lectures supplémentaires, on peut examiner ces discussions concernant les ressources, les barres obliques supprimées et les ressources de limitation actuellement disponibles: disque1 et disque2. Dans l'une des discussions, l'un des auteurs a recommandé de ne pas utiliser les ressources actuellement, mais d'utiliser ce approche à la place.


23
2017-10-10 15:55


origine


Réponses:


Vous ne pouvez pas faire un appel comme celui-ci:

$http({
    method: 'POST',
    url: url,
    data: xsrf,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

le data peut être ce que vous souhaitez passer et puis simplement ajouter &{{csrf_token}} pour que.

Dans votre ressource params:{}, essayez d'ajouter csrfmiddlewaretoken:{{csrf_token}} à l'intérieur de params

Modifier:

Vous pouvez transmettre des données au corps de la requête en tant que

item.$update({csrfmiddlewaretoken:{{csrf_token}}})

et aux en-têtes comme

var csrf = '{{ csrf_token }}'; 
update:{method:'POST', headers: {'X-CSRFToken' : csrf }} 

C'est un sans-papiers problème


7
2017-10-10 17:50



Je sais que c'est plus d'un an, mais si quelqu'un tombe sur le même problème, JS angulaire a déjà un mécanisme de récupération de cookie CSRF (versions d'AngularJS à partir de 1.1.5), et il suffit de dire quel est le nom angulaire. du cookie utilisé par django, ainsi que l’en-tête HTTP qu’il doit utiliser pour communiquer avec le serveur.

Utilisez la configuration du module pour cela:

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

Maintenant, chaque requête aura le bon jeton CSJR Django. A mon avis, c'est beaucoup plus correct que de placer manuellement le jeton sur chaque requête, car il utilise des systèmes intégrés des deux frameworks (django et angularJS).


39
2017-12-10 10:48



Dans la version récente de angularjs, la solution ne fonctionne pas. Donc j'ai essayé ce qui suit

  • Ajoutez d'abord le tag django {% csrf_token%} dans le balisage.

  • Ajoutez un inspecteur $ http dans votre fichier de configuration d'application

angular.module('myApp').config(function ( $httpProvider) {
   $httpProvider.interceptors.push('myHttpRequestInterceptor'); 
});

  • Puis définissez ce que myHttpRequestInterceptor

angular.module("myApp").factory('myHttpRequestInterceptor', function ( ) {

   return {
             config.headers = { 
              'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val() } 
             } 
   return config; 
  }}; 
});

il ajoutera le X-CSRFToken dans toute requête angulaire

Et enfin, vous devez ajouter le middleware Django "django.middleware.csrf.CsrfViewMiddleware" " Il va résoudre le problème CSRF


1
2017-10-19 03:52



var app = angular.module('angularFoo', ....

app.config(["$httpProvider", function(provider) {
  provider.defaults.headers.common['X-CSRFToken'] = '<<csrftoken value from template or cookie>>';
}])

0
2017-08-01 21:46



J'utilise ceci:

Dans la vue Django:

@csrf_protect
def index(request):
    #Set cstf-token cookie for rendered template
    return render_to_response('index.html', RequestContext(request))

Dans App.js:

(function(A) {
    "use strict";
    A.module('DesktopApplication', 'ngCookies' ]).config(function($interpolateProvider, $resourceProvider) {
        //I use {$ and $} as Angular directives
        $interpolateProvider.startSymbol('{$');
        $interpolateProvider.endSymbol('$}');
        //Without this Django not processed urls without trailing slash
        $resourceProvider.defaults.stripTrailingSlashes = false; 
    }).run(function($http, $cookies) {
        //Set csrf-kookie for every request
        $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
        $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    });
}(this.angular));

Pour envoyer une requête correcte, vous devez convertir l'objet en paramètre:

$http.post('/items/add/', $.param({name: 'Foo'}));//Here $ is jQuery

0
2017-12-11 17:53