webentwicklung-frage-antwort-db.com.de

So erstellen Sie eine POST Anfrage (einschließlich CSRF-Token) mit Django und AngularJS

Ich versuche, eine POST -Anforderung mithilfe von angle.js für diese Django-Ansicht zu erstellen.

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)

Deshalb habe ich diese Ressource erstellt.

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'}
    });
});

Das Aufrufen der get -Methode in einem Controller funktioniert einwandfrei. Die URL wird in http://127.0.0.1:8000/pm/rest/tree/1/ übersetzt.

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!'});  
    });
}

Während ich Probleme habe, die Update-/POST-Methode auszuführen.

item.$update();

Die URL wird in http://127.0.0.1:8000/pm/rest/tree/1/345 übersetzt, dem ein nachstehender Schrägstrich fehlt. Dies kann leicht umgangen werden, wenn in Ihrer URL-Definition kein nachstehender Schrägstrich verwendet wird.

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

anstatt

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

Mit der Problemumgehung ohne den nachgestellten Schrägstrich bekomme ich jetzt einen 403 (Forbidden) Statuscode, der wahrscheinlich darauf zurückzuführen ist, dass ich in der Anforderung POST kein CSRF token übergeben habe. Daher läuft meine Frage darauf aus, wie ich das CSRF-Token in die von <wink> erstellte Anforderung POST übergeben kann.

Ich weiß über this Ansatz, um das CSRF-Token über die Header zu übergeben, aber ich suche nach einer Möglichkeit, das Token zum Body der Post-Anfrage hinzuzufügen, wie vorgeschlagen hier . Ist es in eckig möglich, Daten zum Post-Request-Body hinzuzufügen?

Als zusätzliche Lesung kann man sich diese Diskussionen über Ressourcen ansehen, nachfolgende Schrägstriche entfernen und die Ressourcen mit Einschränkungen derzeit haben: disc1 und disc2 ..__ In einer der Diskussionen empfiehlt einer der Autoren derzeit Verwenden Sie keine Ressourcen, sondern verwenden Sie stattdessen this .

23
Thomas Kremmel

Kannst du nicht so telefonieren:

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

Die data kann beliebig sein, und Sie fügen einfach &{{csrf_token}} hinzu.

Versuchen Sie in Ihrer Ressource params:{}, csrfmiddlewaretoken:{{csrf_token}} in der params hinzuzufügen.

Bearbeiten:

Sie können Daten an den Anforderungstext als übergeben

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

und zu Headern als

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

Es ist eine undokumentierte Ausgabe

7

Ich weiß, dass dies mehr als ein Jahr alt ist, aber wenn jemand auf dasselbe Problem stößt, verfügt eckige JS bereits über einen CSRF-Cookie-Abrufmechanismus (Versionen von AngularJS ab 1.1.5), und Sie müssen nur sagen, was der Name ist des Cookies, das Django verwendet, und auch den HTTP-Header, mit dem es mit dem Server kommunizieren soll. 

Verwenden Sie dazu die Modulkonfiguration:

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

Jetzt hat jede Anfrage den richtigen Django CSRF-Token. Meiner Meinung nach ist dies viel richtiger als das manuelle Platzieren des Tokens bei jeder Anforderung, da er eingebaute Systeme aus beiden Frameworks (Django und AngularJS) verwendet.

39
Anoyz

In der letzten Version von anglejs funktioniert die Lösung nicht. Also habe ich folgendes versucht 

  • Fügen Sie zunächst das Django-Tag {% csrf_token%} im Markup hinzu.

  • Fügen Sie Ihrer App-Konfigurationsdatei einen $ http-Inspector hinzu 

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

  • Definieren Sie dann diesen myHttpRequestInterceptor 

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

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

es wird das X-CSRFToken in alle Winkelanfragen eingefügt

Als letztes müssen Sie die Django-Middleware "Django.middleware.csrf.CsrfViewMiddleware '" Hinzufügen. Dadurch wird das CSRF-Problem gelöst

1
mdimran

Ich benutze das:

In der Django-Ansicht:

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

In 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));

Um eine korrekte Anfrage zu senden, müssen Sie das Objekt in das param-Formular konvertieren

$http.post('/items/add/', $.param({name: 'Foo'}));//Here $ is jQuery
0
Dunaevsky Maxim
var app = angular.module('angularFoo', ....

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