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