我尝试在调用任何其他端点之前从我的REST API获取身份验证令牌(最好是一次)。 为此,我创建了一个令牌工厂,它调用登录并返回一个令牌。然后,我希望将该令牌工厂注入我的其他控制器。我希望在从令牌工厂获取令牌之前,我的控制器会调用服务的依赖关系。我做错了什么?
工厂:
app.factory('tokenFactory', function($http, appConfig) {
console.log('calling endpoint: ' + appConfig.REST_ENDPOINT + 'authentication/login');
var apiToken;
$http.post(appConfig.REST_ENDPOINT + 'authentication/login', {
"username": "john",
"password": "open$esame"
}).
success(function(data) {
apiToken = data.token;
}).
error(function(data) {
//
});
return {
apiToken: apiToken
};
});
控制器:
app.controller('clientListCtrl', function($scope, $http, appConfig, tokenFactory) {
console.log('calling endpoint: ' + appConfig.REST_ENDPOINT+'/client/list');
$http.get(appConfig.REST_ENDPOINT+'/client/list', {
header: { 'Authorization': tokenFactory.apiToken }
})
.success(function(data) {
$scope.clients = data;
}).
error(function(data, status) {
//
});
});
答案 0 :(得分:1)
是的,您必须考虑Ajax的异步方面并利用承诺链($http.post
实际上返回您需要返回的承诺)。工厂将使用方法getToken
可以定义在收到结果时通知的success
方法。
app.factory('tokenFactory', function($http, appConfig) {
console.log('calling endpoint: ' + appConfig.REST_ENDPOINT + 'authentication/login');
return {
getToken: function() {
return $http.post(appConfig.REST_ENDPOINT + 'authentication/login', {
"username": "john",
"password": "open$esame"
}).
success(function(data) {
return data.token;
}).
error(function(data) {
//
});
}
};
});
那就是说,我认为你应该利用Angular的HTTP拦截器功能。这允许在请求中透明地设置安全令牌。第一次使用AJAX获取令牌,然后您可以重用此令牌。
app.factory('securityTokenInterceptor', function($q, tokenFactory) {
var currentToken = null;
return {
request: function(config) {
if (currentToken != null) {
config.headers['Authorization'] = currentToken;
return config;
}
var deferred = $q.defer();
tokenFactory.getToken().then(function(token) {
config.headers['Authorization'] = token.token;
currentToken = token.token;
deferred.resolve(config);
}, function(err) {
// Handle error (reject promise, ...)
});
return deferred.promise;
}
};
})
以下是在$httpProvider
上注册拦截器的方法:
app.config(function($httpProvider) {
$httpProvider.interceptors.push('securityTokenInterceptor');
})
这是我用来获取令牌的假工厂:
app.factory('tokenFactory', function($q, $timeout) {
return {
getToken: function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve({token:'mytoken'});
}, 500);
return deferred.promise;
}
};
})
希望它可以帮到你, 亨利
答案 1 :(得分:0)
在您的工厂:
$http.post()
是异步的,因此它之后的返回将不包含来自post请求的数据。我建议你回复你从调用$http.post()
获得的promise对象。
在您的控制器中:您可以使用返回的承诺并定义成功方法,您可以在其中执行获取请求。
tokenFactory.success(function (tokenData) {
token = tokenData.token;
$http.get(endpoint, { header: { 'auth': token } })
.success(...)
.error(...);
});
不确定这是否是最好的方法,但我认为它可以这样工作。