Angular JS Controller получает cookie из заголовка запроса на вход в систему даже после выполнения Get после входа в систему

В настоящее время с помощью метода setTimeout я могу успешно делать то, что я хочу. Но это не идеальный подход.

Когда мы отправляем запрос на вход в систему, мы хотим получить токен CSRF из заголовка ответа и использовать его при последующих вызовах http. Запрос http.get() делает это для нас (он устанавливает заголовок ответа логина в заголовок запроса). После этого мы хотим снова выполнить запрос на публикацию на основе ответа, который мы получаем из запроса http.get() внутри обратного вызова входа в систему.

Проблема здесь в том, что код выполняется до того, как браузер завершает работу, устанавливая токен CSRF, полученный из ответа, в заголовок запроса. Чтобы преодолеть эту проблему, я добавил функцию setTimeout. Но мне не очень нравится подход добавления жестко заданной задержки.

Есть ли эффективный способ сделать это?

        app.controller('loginCtrl', function ($scope, $http, $location, $cookies, $q, Cart,$rootScope)
{
        var defer = $q.defer();

        $scope.submit = function(){

                $http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;application/JSON";
                //login
                $http.post('http://127.0.0.1:8000/api/user/login/', JSON.stringify({'email': $scope.email, 'password': $scope.password})
                ).success(function(data){

                defer.promise.then(function(){
                //need to get a cart to check if a cart is created
                    Cart.getCart(function(data){


                    defer.promise.then(function(){
               //if cart not created create one
                        if(data.length == 0){
                            setTimeout(function(){
                                $http.defaults.headers.common["X-CSRFToken"] = $cookies.csrftoken;
                                Cart.addCart(function(data){
                                    alert('cart successfully created \n ' + JSON.stringify(data));
                                    $rootScope.cartId = data[0].pk
                                    $rootScope.cart = data[0].fields;
                                    $location.path('/products');
                                }, function(error){
                                    alert('addcart failed');
                            });
                            },300);

                        } else {
                            $rootScope.cartId = data[0].pk;
                            $rootScope.cart = data[0].fields;
                            $location.path('/products');
                        }

             })

                }, function(error){
                    alert('getcart failed');
                });
            })
                //need code to get the cookies, still dont know how

                }).error(function(data){
                alert('failure');
                });


        defer.resolve();        
        };
});

2 ответа

Решение

Возможно, вы могли бы перехватить ответ, разобрать заголовки и установить токен вручную.

Что-то вроде этого:

module.factory('xsrfTokenInterceptor', function ($q, $http) {
    return {
        'response': function (response) {
            var cookies = response.headers("Set-Cookie");
            var token = someCrazyParsing(cookies);
            $http.defaults.headers.common["X-CSRFToken"]=token;
            return response || $q.when(response);
        }  
    };
});
module.config(function($httpProvider){
    $httpProvider.interceptors.push('xsrfTokenInterceptor')
})

РЕДАКТИРОВАТЬ НОВЫЙ ПОДХОД

Может как то так?

module.factory('LoginService', function ($q, $http) {
    var login = function (email, password) {
        var defered = $q.defer();
        $http.post('http://127.0.0.1:8000/api/user/login/', {
                'email': email,
                'password': password
        }).success(function (data, status, headers, config) {
            var cookies = headers("Set-Cookie");
            var token = someCrazyParsing(cookies); //<-- Your magic here
            $http.defaults.headers.common["X-CSRFToken"] = token;
            defered.resolve(data);
        }).error(function (data, status, headers, config) {
            defered.reject(data);
        });
        return defered.promise;
    };
    return {
        login: login
    };
});

module.controller("LoginCtrl", function ($scope, LoginService, Cart) {
    $scope.submit = function () {
        LoginService.login($scope.email, $scope.password).then(function (data) {
            Cart.getCart(function (data) {});
        });
    };
});

Это работает, если вы настраиваете это глобально?

module.config(function ($httpProvider) {
    $httpProvider.defaults.xsrfHeaderName = "X-CSRFToken";
    $httpProvider.defaults.xsrfCookieName = "csrftoken";
});
Другие вопросы по тегам