Angularjs angular js controller从登录请求头获取cookie,即使在登录后执行Get操作

Angularjs angular js controller从登录请求头获取cookie,即使在登录后执行Get操作,angularjs,cookies,csrf,promise,django-csrf,Angularjs,Cookies,Csrf,Promise,Django Csrf,目前,通过使用setTimeout方法,我能够成功地完成我想做的事情。但这不是理想的方法 当我们发送登录请求时,我们希望从响应头获取CSRF令牌,并在后续http调用中使用它。get()请求为我们完成了这一任务(它将登录名的响应头设置为请求头)。之后,我们希望根据登录回调中http.get()请求的响应再次执行post请求 这里的问题是,代码在浏览器完成之前执行,将从响应接收到的CSRF令牌设置到请求头中。为了克服这个问题,我添加了一个setTimeout函数。但我真的不喜欢添加硬编码延迟的方法

目前,通过使用setTimeout方法,我能够成功地完成我想做的事情。但这不是理想的方法

当我们发送登录请求时,我们希望从响应头获取CSRF令牌,并在后续http调用中使用它。get()请求为我们完成了这一任务(它将登录名的响应头设置为请求头)。之后,我们希望根据登录回调中http.get()请求的响应再次执行post请求

这里的问题是,代码在浏览器完成之前执行,将从响应接收到的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();        
        };
});

如果您全局配置它,它能工作吗

module.config(function ($httpProvider) {
    $httpProvider.defaults.xsrfHeaderName = "X-CSRFToken";
    $httpProvider.defaults.xsrfCookieName = "csrftoken";
});

也许您可以拦截响应,解析头并手动设置令牌

大概是这样的:

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.factory('LoginService',函数($q,$http){
var login=函数(电子邮件、密码){
var defered=$q.defer();
$http.post('http://127.0.0.1:8000/api/user/login/', {
“电子邮件”:电子邮件,
“密码”:密码
}).success(函数(数据、状态、标题、配置){
var cookies=标题(“设置Cookie”);

var token=someCrazyParsing(cookies);//我无法将代码与文字描述的内容联系起来。@Beetroot Beetroot我可以尝试解释我在这个项目中遇到的问题。我们向Django应用程序发送一个POST请求以进行登录。登录后,我们发送一个“获取用户的购物车”,如果没有用户的购物车,我们将创建一个新的购物车(您可以看到,在上面的代码中,我们正在检查data.length==0)。如果没有购物车,我们会发布一个创建购物车的请求。在Django中,我们必须在POST请求中设置X-CSRFToken。如果我们没有在setTimeout函数中调用addCart函数调用,POST请求中的X-CSRF与登录响应中设置的X-CSRF不一样,并给出401errAh权限,代码有点混乱。大概是
defer
在尝试使它工作时引入。据我所知,它不是必需的,可以安全删除。剩下的看起来应该可以工作,但似乎在设置
$http.defaults.headers.common[“X-CSRFToken”]中存在某种竞争效应
。非常奇怪,因为设置默认标头应该是可靠同步的。获取以下错误:“未捕获错误:[$injector:cdep]”当我们加载登录页面,整个部分停止显示时,控制台上会弹出此错误。嗯,很有趣,但有意义,因为拦截器依赖于http,但在创建interceper时http尚未创建。根据新的解决方案,我无法调用Cart.getCart()api。我可以在网络中看到登录成功,状态为200。这是一个相当老的问题,但似乎这个解决方案不起作用,也就是说,即使在标题中进行监视,我也可以看到“Set Cookie”、
标题(“Set Cookie”);
为空。您可以通过再次调用
$cookiesProvider.$get()
函数来重新生成新的本地
$cookies
。为此,我羞愧地创建了对
$cookiesProvider
的本地引用:
var cookiesProvider\u ref=null;app.config(函数($cookiesProvider){cookiesProvider\u ref=$cookiesProvider})
。然后在登录
success()
回调中使用
cookiesProvider\u ref
再次设置
$http
csrf令牌头字段。