我有一个有角度的应用程序,有时每个状态会执行多个$ http.get请求。该应用程序使用JWT进行用户验证刷新令牌。 API服务器在由于auth错误而失败的每个请求发送401。
我制作了一个http拦截器,请求一个新的令牌与401错误的刷新令牌,然后重新发送原始请求。
我制作了一个http拦截器,请求一个新的令牌与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,只需使用缓存的承诺,而不是发起新的请求。
- app.factory('AuthInterceptor',authService) {
- var inFlightAuthRequest = null;
- return {
- request: function(config) {
- config.headers = config.headers || {};
- if (authService.getAccessToken()) {
- if (config.url.substring(0,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(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);
- }
- };
- });