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