AngularJS-HTTP拦截器-令牌刷新后重新发送所有请求

我有一个有角度的应用程序,有时每个状态会执行多个$

http.get请求。该应用将JWT用于带有刷新令牌的用户身份验证。API服务器会发送401由于身份验证错误而失败的每个请求。我做了一个http

interceptor请求,该请求在401错误时请求带有刷新令牌的新令牌,然后重新发送原始请求。

问题是,如果一个状态发出例如2个$

http.get请求,并且都获得401响应,那么我将访问令牌更新两次。显然,我只想刷新一次令牌,但是我仍然想重新发送两个失败的请求。

这是可以实现的吗?

app.factory('AuthInterceptor', function($q, $injector, RESOURCE_URL, API_BASE, authService) {

return {

request: function(config) {

config.headers = config.headers || {};

if (authService.getAccessToken()) {

if (config.url.substring(0, RESOURCE_URL.length) !== RESOURCE_URL) {

config.headers.Authorization = 'Bearer ' + authService.getAccessToken();

}

}

return config;

},

responseError: function(response) {

switch (response.status) {

case 401:

var deferred = $q.defer();

$injector.get("$http").post(API_BASE + '/api/auth/refresh', {refreshtoken: authService.getRefreshToken()}).then(function(r) {

if (r.data.data.accesstoken && r.data.data.refreshtoken && r.data.data.expiresin) {

authService.setAccessToken(r.data.data.accesstoken);

authService.setRefreshToken(r.data.data.refreshtoken);

authService.setExpiresIn(r.data.data.expiresin);

$injector.get("$http")(response.config).then(function(resp) {

deferred.resolve(resp);

},function(resp) {

deferred.reject();

});

} else {

deferred.reject();

}

}, function(response) {

deferred.reject();

authService.clear();

$injector.get("$state").go('guest.login');

return;

});

return deferred.promise;

break;

default:

authService.clear();

$injector.get("$state").go('guest.login');

break;

}

return response || $q.when(response);

}

};

});

回答:

您的拦截器需要跟踪其是否有“运行中”的身份验证请求。它可以通过保留对身份验证请求返回的承诺的引用来实现。如果有一个正在处理中的请求,而您又收到另一个401,则只需使用该缓存的Promise即可,而不是发起新的请求。另外,您应该考虑添加逻辑以解决’/

api / auth / refresh’本身返回401的情况。

app.factory('AuthInterceptor', function($q, $injector, RESOURCE_URL, API_BASE, authService) {

var inflightAuthRequest = null;

return {

request: function(config) {

config.headers = config.headers || {};

if (authService.getAccessToken()) {

if (config.url.substring(0, RESOURCE_URL.length) !== RESOURCE_URL) {

config.headers.Authorization = 'Bearer ' + authService.getAccessToken();

}

}

return config;

},

responseError: function(response) {

switch (response.status) {

case 401:

var deferred = $q.defer();

if(!inflightAuthRequest) {

inflightAuthRequest = $injector.get("$http").post(API_BASE + '/api/auth/refresh', {refreshtoken: authService.getRefreshToken()});

}

inflightAuthRequest.then(function(r) {

inflightAuthRequest = null;

if (r.data.data.accesstoken && r.data.data.refreshtoken && r.data.data.expiresin) {

authService.setAccessToken(r.data.data.accesstoken);

authService.setRefreshToken(r.data.data.refreshtoken);

authService.setExpiresIn(r.data.data.expiresin);

$injector.get("$http")(response.config).then(function(resp) {

deferred.resolve(resp);

},function(resp) {

deferred.reject();

});

} else {

deferred.reject();

}

}, function(response) {

inflightAuthRequest = null;

deferred.reject();

authService.clear();

$injector.get("$state").go('guest.login');

return;

});

return deferred.promise;

break;

default:

authService.clear();

$injector.get("$state").go('guest.login');

break;

}

return response || $q.when(response);

}

};

});

以上是 AngularJS-HTTP拦截器-令牌刷新后重新发送所有请求 的全部内容, 来源链接: utcz.com/qa/400812.html

回到顶部