- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我已经实现了身份验证系统,并且在从 angular 1.0.8 升级到 1.2.x 之后,系统不能像以前那样工作。当用户登录时,它会获得一个 token 。当 token 过期时,调用新 token 的刷新函数。新 token 已在服务器上成功创建,并且是存入数据库。但是客户端没有得到这个新 token ,所以它再次请求一个新 token ,一次又一次,直到它注销。服务器端(MVC Web Api)工作正常,所以问题一定在客户端。问题一定在重试队列上。下面我粘贴了相关代码和两个版本的应用程序(1.0.8 和 1.2.x)的控制台跟踪。我已经为此苦苦挣扎了好几天,但我无法弄清楚。
在下面的链接中,有5个相关的代码块:
代码:http://pastebin.com/Jy2mzLgj
Angular 1.0.8 中应用程序的控制台跟踪:http://pastebin.com/aL0VkwdN
和 Angular 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');
}]);
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;
}]);
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;
}]);
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/
我正在开发一个应用程序,它使用 OAuth - 基于 token 的身份验证。 考虑到我们拥有访问和刷新 token ,这就是流程的样子。 Api call -> intercepter append
如何取消标记此代码的输出? 类(class)核心: def __init__(self, user_input): pos = pop(user_input) subject = ""
当我使用命令 kubectl 时与 --token标记并指定 token ,它仍然使用 kubeconfig 中的管理员凭据文件。 这是我做的: NAMESPACE="default" SERVICE
我正在制作 SPA,并决定使用 JWT 进行身份验证/授权,并且我已经阅读了一些关于 Tokens 与 Cookies 的博客。我了解 cookie 授权的工作原理,并了解基本 token 授权的工作
我正在尝试从应用服务获取 Google 的刷新 token ,但无法。 日志说 2016-11-04T00:04:25 PID[500] Verbose Received request: GET h
我正在开发一个项目,只是为了为 java 开发人员测试 eclipse IDE。我是java新手,所以我想知道为什么它不起作用,因为我已经知道该怎么做了。这是代码: public class ecli
我正在尝试使用 JwtSecurityTokenHandler 将 token 字符串转换为 jwt token 。但它出现错误说 IDX12709: CanReadToken() returned
我已阅读文档 Authentication (来自 Facebook 的官方)。我仍然不明白 Facebook 提供的这三种访问 token 之间的区别。网站上给出了一些例子,但我还是不太明白。 每个
我的部署服务器有时有这个问题,这让我抓狂,因为我无法在本地主机中重现,我已经尝试在我的 web.config 中添加机器 key ,但没有成功远。 它只发生在登录页面。 我的布局:
我已经设法获得了一个简单的示例代码,它可以创建一个不记名 token ,还可以通过阅读 stackoverflow 上的其他论坛来通过刷新 token 请求新的不记名 token 。 启动类是这样的
如果我有以前的刷新 token 和使用纯 php 的访问 token ,没有 Google Api 库,是否可以刷新 Google Api token ?我在数据库中存储了许多用户刷新和访问 toke
我通过 Java 应用程序使用 Google 电子表格时遇到了问题。我创建了应用程序,该应用程序运行了 1 年多,没有任何问题,我什至在 Create Spreadsheet using Google
当我有一个有效的刷新 token 时,我正在尝试使用 Keycloak admin REST API 重新创建访问 token 。 我已经通过调用 POST/auth/realms/{realm}/p
我正在尝试让第三方 Java 客户端与我编写的 WCF 服务进行通信。 收到消息时出现如下异常: Cannot find a token authenticator for the 'System.I
在尝试将数据插入到我的 SQl 数据库时,我收到以下错误 System.Data.SqlServerCe.SqlCeException: There was an error parsing the
使用数据库 session token 系统,我可以让用户使用用户名/密码登录,服务器可以生成 token (例如 uuid)并将其存储在数据库中并将该 token 返回给客户端。其上的每个请求都将包
我最近注册了 Microsoft Azure 并设置了认知服务帐户。使用 Text Translation API Documentation 中的说明我能够使用 interactive online
我使用 IAntiforgery API 创建了一个 ASP.Net Core 2 应用程序。 这提供了一种返回 cookie 的方法。 客户端获取该 cookie,并在后续 POST 请求中将该值放
我正在使用 spacy 来匹配某些文本(意大利语)中的特定表达式。我的文本可以多种形式出现,我正在尝试学习编写一般规则的最佳方式。我有如下 4 个案例,我想写一个适用于所有案例的通用模式。像这样的东西
我无法理解 oauth 2.0 token 的原则处理。 我的场景是,我有一个基于 web 的前端后端系统,带有 node.js 和 angular 2。用户应该能够在此站点上上传视频。然后创建一些额
我是一名优秀的程序员,十分优秀!