gpt4 book ai didi

javascript - AngularJs - 在等待新 token 时不会跳过请求

转载 作者:搜寻专家 更新时间:2023-11-01 04:17:05 25 4
gpt4 key购买 nike

我已经实现了身份验证系统,并且在从 angular 1.0.8 升级到 1.2.x 之后,系统不能像以前那样工作。当用户登录时,它会获得一个 token 。当 token 过期时,调用新 token 的刷新函数。新 token 已在服务器上成功创建,并且是存入数据库。但是客户端没有得到这个新 token ,所以它再次请求一个新 token ,一次又一次,直到它注销。服务器端(MVC Web Api)工作正常,所以问题一定在客户端。问题一定在重试队列上。下面我粘贴了相关代码和两个版本的应用程序(1.0.8 和 1.2.x)的控制台跟踪。我已经为此苦苦挣扎了好几天,但我无法弄清楚。

在下面的链接中,有5个相关的代码块:

  • interceptor.js(用于拦截请求,两个版本)
  • retryQueue.js(管理重试请求队列)
  • security.js(管理重试队列项的处理程序并从 api 获取新 token )
  • httpHeaders.js(设置标题)
  • tokenHandler.js(处理 cookie 中的 token )

代码:http://pastebin.com/Jy2mzLgj

Angular 1.0.8 中应用程序的控制台跟踪:http://pastebin.com/aL0VkwdN

和 Angular 1.2.x:http://pastebin.com/WFEuC6WB

interceptor.js (angular 1.2.x 版本)

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');
}]);

重试队列.js

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

安全.js

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

session.service.js

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

感谢@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;
}

非常感谢,贾尼

最佳答案

您是否尝试修复 1.2 日志中的错误?

Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: project in client.projects, Duplicate key: string:e

该错误恰好出现在您需要查看 $httpHeaders 设置行的位置。看起来你的 session.tokenrefresh 不工作(并且该代码也从 pastebin 中丢失,所以我无法检查。)

关于javascript - AngularJs - 在等待新 token 时不会跳过请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23383616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com