我对Angular很新。我在Angular应用程序中使用令牌身份验证。我使用HTTP拦截器来检查我的后端何时返回401,而不是使用刷新令牌进行登录:
myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector) {
var sessionRecoverer = {
responseError: function(response) {
// Session has expired
if (response.status === 401) {
var $http = $injector.get('$http');
var deferred = $q.defer();
var $auth = $injector.get('$auth');
$auth.login({
refresh_token: ????,
grant_type: 'refresh_token',
event_client: 'client',
client_id: 'id'
});
// When the session recovered, make the same backend call again and chain the request
return deferred.promise.then(function() {
return $http(response.config);
});
}
return $q.reject(response);
}
};
return sessionRecoverer;
}]);
现在,refresh_token来自我的登录控制器(它从api后端拉出)。所以控制器必须以某种方式将它传递给拦截器。问题是拦截器在配置块中,所以没有服务,值等 - 只有提供者。但是提供者不能注入控制器。那么有没有办法将数据从控制器传递到app.config?如果没有,是否有解决方法?注入器可以在除app.config以外的任何其他位置吗?
答案 0 :(得分:1)
是的,你可以这样做:
myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector, TokenFactory) {
var sessionRecoverer = {
responseError: function(response) {
// Session has expired
if (response.status === 401) {
var $http = $injector.get('$http');
var deferred = $q.defer();
var $auth = $injector.get('$auth');
$auth.login({
refresh_token: TokenFactory.getRefreshToken(),
grant_type: 'refresh_token',
event_client: 'client',
client_id: 'id'
});
// When the session recovered, make the same backend call again and chain the request
return deferred.promise.then(function() {
return $http(response.config);
});
}
return $q.reject(response);
}
};
return sessionRecoverer;
}]);
正如你所说,块配置只能注入提供者,但是拦截器本身就是工厂,因此你可以注入其他工厂,例如,一个名为TokenFactory的工厂,它应该提供一个返回刷新令牌的方法。需要的。
如果refresh_token是来自后端的东西,并且您想在登录控制器中设置TokenFactory中的值,那么您可以执行以下操作来实现工厂和控制器:
myapp.factory('TokenFactory',function(){
var currentRefreshToken;
return {
setRefreshToken: function(token){
currentRefreshToken = token;
},
getRefreshToken: function(){
return currentRefreshToken:
}
};
});
myapp.controller('MyLoginCtrl',function($scope,TokenFactory,$http){
$scope.login = function(){
$http.post('http://myapp.com/refreshtoken',$scope.credentials)
.then(TokenFactory.setRefreshToken)
.then(function(){ /* ... */})
.catch(function(err){ console.error(err) })
;
};
});
如果您想让自己的代币持续存在,可以编写一个使用LocalStorage HTML5 API
的工厂并在TokenFactory
中使用它:
myapp.factory('TokenFactory',function(LocalStorage){
// load the value from localstorage (hard disk) on app starts
var currentRefreshToken = LocalStorage.get('myapp.currentRefreshToken');
return {
setRefreshToken: function(token){
currentRefreshToken = token; // save value in RAM
LocalStorage.set('myapp.currentRefreshToken',token); // and sync the localstorage value
},
getRefreshToken: function(){
return currentRefreshToken; // quick access to the value from RAM
}
};
});
myapp.factory('LocalStorage',function($window) {
var localStorage = {};
localStorage.set = function(key, value) {
$window.localStorage[key] = value;
};
localStorage.get = function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
};
localStorage.setObject = function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
};
localStorage.getObject = function(key) {
return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? {} : JSON.parse($window.localStorage[key]);
};
localStorage.setArray = function(key, array){
if (!array.length) {
console.debug(array);
$window.localStorage[key] = '[]';
} else{
this.setObject(key, array);
}
};
localStorage.getArray = function(key){
return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? [] : JSON.parse($window.localStorage[key]);
};
localStorage.exportAsFile = function(key, fileName){
var data = [$window.localStorage[key]] || ['{}'];
var blob = new Blob(data,{type:'application/json;charset=utf-8'});
$window.saveAs(blob,fileName);
};
return localStorage;
});