如何在AngularJS中刷新过期的jwt令牌
问题描述:
我正在开发一个Angular webapp,它使用API来获取一些数据。 要获得这些数据,我必须发送一个智威汤逊。 我创建,为了调用一个PHP文件,以获得令牌服务:如何在AngularJS中刷新过期的jwt令牌
(function() {
'use strict';
angular
.module('MyApp')
.factory('TokenService', Service);
function Service($http, $localStorage) {
var service = {};
service.getToken = getToken;
return service;
function getToken() {
return $http.post('gettoken.php');
}
}})();
而我做的是在.RUN块我把它和存储接收的令牌:
function run($rootScope, $http, $location, $localStorage, TokenService) {
TokenService.getToken().then(function(response) {
$localStorage.token = response.data.token;
});
console.log('token: ' + $localStorage.token);
$http.defaults.headers.common.Authorization = 'Bearer ' + $localStorage.token;
}})();
每过几分钟,令牌就会过期,因此我必须请求另一个令牌,以便用户可以继续与API进行交互。
为了解决这个问题,我的第一个方法是使用.config块拦截401错误(令牌过期)并要求另一个令牌,但这是不可能的,因为据我所知,不可能注入服务的.config块:
function config2($httpProvider) {
$httpProvider.interceptors.push(function ($q, $rootScope) {
return {
'response': function (response) {
//Will only be called for HTTP up to 300
console.log(response);
return response;
},
'responseError': function (rejection) {
if(rejection.status === 401) {
var deferred = $q.defer();
TokenService.getToken(function() {
retryHttpRequest(response.config, deferred);
});
return deferred.promise;
} else {
return response;
}
function retryHttpRequest(config, deferred){
function successCallback(response){
deferred.resolve(response);
}
function errorCallback(response){
deferred.reject(response);
}
var $http = $injector.get('$http');
$http(config).then(successCallback, errorCallback);
}
}
};
});
}
事实上,当我执行的web应用程序,它说,TokenService没有定义,如果我注入TokenService,显然它创建了一个圆圈扶养:
angular.js:66 Uncaught Error: [$injector:cdep] Circular dependency found: $http <- TokenService <- $http <- $templateRequest <- $route
http://errors.angularjs.org/1.6.4/$injector/cdep?p0=%24http%20%3C-%20TokenService%20%3C-%20%24http%20%3C-%20%24templateRequest%20%3C-%20%24route
at angular.js:66
at getService (angular.js:4936)
at injectionArgs (angular.js:4969)
at Object.invoke (angular.js:4995)
at Object.enforcedReturnValue [as $get] (angular.js:4836)
at Object.invoke (angular.js:5003)
at angular.js:4795
at getService (angular.js:4944)
at injectionArgs (angular.js:4969)
at Object.invoke (angular.js:4995)
这是一个非常愚蠢的情况,但我花了整整一天试图fi寻找最佳解决方案。 一旦拦截器检测到401 responseError,我试图简单地重新加载页面,但这不是最佳的,因为用户看到网络刷新,并且他丢失了为请求插入的所有数据。
如果有的话,你不得不处理这类问题,可以为了解决它共享任何方式这将是巨大的。
答
这可能是因为$http
服务取决于您的拦截器,您的TokenService
取决于$http
服务,而您的拦截器取决于TokenService
。这会导致循环依赖。
看来你已经在使用$injector
来即时注入$ http-service,所以要解决你的循环依赖问题,用同样的方法注入你的TokenService
可能会解决你的问题。
var TokenService = $injector.get('TokenService');
我之前在同样的问题,迷迷糊糊的,所以如果它的任何帮助,您可以check my solution on GitHub。
非常感谢您的帮助。 我应用了你说的。现在的问题是当我在ResponseError中调用getToken时:它返回新的令牌,但它不适用于当前的401请求,所以我收到新的令牌,但对API的请求仍然失败。 我正在阅读你的解决方案在GitHub上,我希望我可以用该代码解决它。 非常感谢! – Hmorv
我终于用你的工厂作为例子调整了我的代码。它的作品相当不错!谢谢! – Hmorv