Angularjs: 在 $http 拦截器中发出另一个 $http 请求

Angularjs: Making another $http request inside a $http interceptor

我有一个简单的(完成一半的)http 拦截器,它将 Bearer 令牌(存储在 $window.sessionsStorage 中)附加到 header 以便 REST API 请求可以被认证:

function accessTokenHttpInterceptor($window, $http) {

  // Try to get token details from sessionStorage
  var accesstoken=$window.sessionStorage.getItem('userInfo-accesstoken');
  var refreshtoken=$window.sessionStorage.getItem('userInfo-refreshtoken');
  var tokenexpiry=$window.sessionStorage.getItem('userInfo-tokenexpiry');

  return {

    request: function($config) {

      // Check if the access token, refresh token and expiry date exists:
      if (accesstoken == undefined || refreshtoken == undefined || tokenexpiry == undefined) {
        console.log('Missing token details');
        // TODO REDIRECT TO LOGIN PAGE
      }

      // We have an access token. Has it expired?
      var expiry = new Date($window.sessionStorage['userInfo-tokenexpiry'])
      var now = new Date
      if (now > expiry ) {
        console.log('Token expired');
        // TODO REFRESH THE TOKEN
        };

      // Set the authorization header
      $config.headers['Authorization'] = 'Bearer ' + accesstoken;
      return $config;

    },
  };
}

accessTokenHttpInterceptor.$inject=['$window'];

function httpInterceptorRegistry($httpProvider) {
    $httpProvider.interceptors.push('accessTokenHttpInterceptor');
}

angular
    .module('myApp')
    .config(httpInterceptorRegistry)
    .factory('accessTokenHttpInterceptor', accessTokenHttpInterceptor)

如您所见,我能够在调用 API 之前查看令牌是否已过期。

任何人都可以帮助我在发出实际 API 请求之前如何刷新令牌吗?我认为发出另一个 $http 请求会再次被拦截并最终陷入无限循环。 通过向 API 发出 POST 请求来刷新令牌,其中刷新令牌作为参数传递,而不是像其他 API 请求一样在授权 header 中。

您可以检查请求的 url 以防止无限循环。此外,您可以 return 一个使用它解决的承诺,而不是直接 returning 配置,这样您就可以等到获得有效令牌。例如

{
    request: function(config) {
        if(config.url != 'my/refresh/url') {
            var promiseToHaveValidToken;

            var expiry = new Date($window.sessionStorage['userInfo-tokenexpiry']);
            var now = new Date();
            if (now > expiry ) {
                promiseToHaveValidToken = $http.get('my/refresh/url').then(function (response) {
                    return response.data.token;
                });
            } else {
                promiseToHaveValidToken = $q.resolve(sessionStorage['userInfo-accesstoken']);
            }

            return promiseToHaveValidToken.then(function (token) {
                config.headers['Authorization'] = 'Bearer ' + token;
                return config;
            });
        }
    }
}