h3n*_*1ks 5 javascript angularjs
我已经实现了身份验证系统,从角度1.0.8升级到1.2.x后,系统无法正常工作.当用户登录时获取令牌.令牌过期时,将调用新令牌的刷新功能.在服务器上成功创建新令牌,并将其存储到数据库.但是客户端没有获得这个新令牌,因此它再次请求一个新令牌,并一次又一次地请求它直到它注销.服务器端(MVC Web Api)工作正常,因此问题必须在客户端.问题必须在重试队列上.下面我粘贴了两个版本的应用程序(1.0.8和1.2.x)的相关代码和控制台跟踪.我现在正在努力奋斗这几天,我无法弄明白.
在下面的链接中,有5个相关的代码块:
代码:http://pastebin.com/Jy2mzLgj
应用程序的控制台跟踪角度为1.0.8:http://pastebin.com/aL0VkwdN
和角度1.2.x:http://pastebin.com/WFEuC6WB
angular.module('security.interceptor', ['security.retryQueue'])
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', '$q',
function ($injector, queue, $q) {
return {
response: function(originalResponse) {
return originalResponse;
},
responseError: function (originalResponse) {
var exception;
if (originalResponse.headers){
exception = originalResponse.headers('x-eva-api-exception');
}
if (originalResponse.status === 401 &&
(exception === 'token_not_found' ||
exception === 'token_expired')){
queue.pushRetryFn(exception, function retryRequest() {
return $injector.get('$http')(originalResponse.config);
});
}
return $q.reject(originalResponse);
}
};
}])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('securityInterceptor');
}]);
Run Code Online (Sandbox Code Playgroud)
angular.module('security.retryQueue', [])
.factory('securityRetryQueue', ['$q', '$log', function($q, $log) {
var retryQueue = [];
var service = {
onItemAddedCallbacks: [],
hasMore: function(){
return retryQueue.length > 0;
},
push: function(retryItem){
retryQueue.push(retryItem);
angular.forEach(service.onItemAddedCallbacks, function(cb) {
try {
cb(retryItem);
}
catch(e){
$log.error('callback threw an error' + e);
}
});
},
pushRetryFn: function(reason, retryFn){
if ( arguments.length === 1) {
retryFn = reason;
reason = undefined;
}
var deferred = $q.defer();
var retryItem = {
reason: reason,
retry: function() {
$q.when(retryFn()).then(function(value) {
deferred.resolve(value);
}, function(value){
deferred.reject(value);
});
},
cancel: function() {
deferred.reject();
}
};
service.push(retryItem);
return deferred.promise;
},
retryAll: function() {
while(service.hasMore()) {
retryQueue.shift().retry();
}
}
};
return service;
}]);
Run Code Online (Sandbox Code Playgroud)
angular.module('security.service', [
'session.service',
'security.signin',
'security.retryQueue',
'security.tokens',
'ngCookies'
])
.factory('security', ['$location', 'securityRetryQueue', '$q', /* etc. */ function(){
var skipRequests = false;
queue.onItemAddedCallbacks.push(function(retryItem) {
if (queue.hasMore()) {
if(skipRequests) {return;}
skipRequests = true;
if(retryItem.reason === 'token_expired') {
service.refreshToken().then(function(result) {
if(result) { queue.retryAll(); }
else {service.signout(); }
skipRequests = false;
});
} else {
skipRequests = false;
service.signout();
}
}
});
var service = {
showSignin: function() {
queue.cancelAll();
redirect('/signin');
},
signout: function() {
if(service.isAuthenticated()){
service.currentUser = null;
TokenHandler.clear();
$cookieStore.remove('current-user');
service.showSignin();
}
},
refreshToken: function() {
var d = $q.defer();
var token = TokenHandler.getRefreshToken();
if(!token) { d.resolve(false); }
var session = new Session({ refreshToken: token });
session.tokenRefresh(function(result){
if(result) {
d.resolve(true);
TokenHandler.set(result);
} else {
d.resolve(false);
}
});
return d.promise;
}
};
return service;
}]);
Run Code Online (Sandbox Code Playgroud)
angular.module('session.service', ['ngResource'])
.factory('Session', ['$resource', '$rootScope', function($resource, $rootScope) {
var Session = $resource('../api/tokens', {}, {
create: {method: 'POST'}
});
Session.prototype.passwordSignIn = function(ob) {
return Session.create(angular.extend({
grantType: 'password',
clientId: $rootScope.clientId
}, this), ob);
};
Session.prototype.tokenRefresh = function(ob) {
return Session.create(angular.extend({
grantType: 'refresh_token',
clientId: $rootScope.clientId
}, this), ob);
};
return Session;
}]);
Run Code Online (Sandbox Code Playgroud)
感谢@Zerot的建议和代码示例,我不得不改变拦截器的一部分,如下所示:
if (originalResponse.status === 401 &&
(exception === 'token_not_found' || exception === 'token_expired')){
var defer = $q.defer();
queue.pushRetryFn(exception, function retryRequest() {
var activeToken = $cookieStore.get('authorization-token').accessToken;
var config = originalResponse.config;
config.headers.Authorization = 'Bearer ' + activeToken;
return $injector.get('$http')(config)
.then(function(res) {
defer.resolve(res);
}, function(err)
{
defer.reject(err);
});
});
return defer.promise;
}
Run Code Online (Sandbox Code Playgroud)
非常感谢,Jani
小智 2
您是否尝试修复 1.2 日志中的错误?
错误:[ngRepeat:dupes] 不允许在转发器中重复。使用“track by”表达式来指定唯一键。中继器:client.projects 中的项目,重复键:字符串:e
该错误正是在您需要查看 $httpHeaders 设置行的位置。看起来您的 session.tokenrefresh 不起作用(并且 Pastebin 中也缺少该代码,所以我无法检查。)
| 归档时间: |
|
| 查看次数: |
1041 次 |
| 最近记录: |