如果刷新(JWT)代币未经授权(401响应),则AngularJS重定向登录



如果refresh(JWT)令牌未经授权(在第一个令牌到期之后),我将面临重定向用户登录页面。有2种代币授权的情况;

  • 1st:当JWT令牌基于401响应到期时,与新的刷新服务相比,通过$ http-Interceptors(config)。

  • 第二:当刷新令牌也未经授权(401)响应时,这是用户应重定向到登录页面的时候。

我能够在第一个方案中发送刷新令牌及其正常工作,但是如果刷新令牌也未经授权(401)响应,我将无法重定向用户登录页面。

这是我的代码;

authinterceptor.service.js

angular.module('someApp').factory('AuthorizationTokenService', AuthorizationTokenService);
AuthorizationTokenService.$inject = ['$q', '$injector', '$cookies'];
function AuthorizationTokenService($q, $injector, $cookies) {
  // Local storage for token
  var tokenVM = {
    accessToken: null
  };
  // Subscribed listeners which will get notified when new Access Token is available
  var subscribers = [];
  // Promise for getting new Access Token from backend
  var deferedRefreshAccessToken = null;
  var service = {
    getLocalAccessToken: getLocalAccessToken,
    refreshAccessToken: refreshAccessToken,
    isAccessTokenExpired: isAccessTokenExpired,
    subscribe: subscribe
  };
  return service;
  ////////////////////////////////////
  // Get the new Access Token from backend
  function refreshAccessToken() {
    // If already waiting for the Promise, return it.
    if( deferedRefreshAccessToken ) {
      return deferedRefreshAccessToken.promise 
    } else {
      deferedRefreshAccessToken = $q.defer();
      // Get $http service with $injector to avoid circular dependency
      var http = $injector.get('$http');
      http({
        method: 'POST',
        url: 'api_url',
        params: {
          grant_type: 'refresh',
          id_token: $cookies.get('access_token')
        }
      })
        .then(function mySucces(response) {
          var data = response.data;
          if( data ){
            // Save new Access Token
            $cookies.put('access_token', data.access_token);
            if( $cookies.get('access_token') ) {
              // Resolve Promise
              deferedRefreshAccessToken.resolve(data.access_token);
              // Notify all subscribers
              notifySubscribersNewAccessToken(data.access_token);
              deferedRefreshAccessToken = null;
            }
          }
        }, function myError(error) {
          deferedRefreshAccessToken.reject(error);
          deferedRefreshAccessToken = null;
        });
      return deferedRefreshAccessToken.promise;
    } 
  }
  function getLocalAccessToken() {
    // get accesstoken from storage - $cookies
    if ( $cookies.get('access_token') ) {
      var access_token = $cookies.get('access_token')
      return access_token;
    }
  }
  function isAccessTokenExpired() {
    // Check if expiresAt is older then current Date
  }
  function saveToken(accessToken) {
    // get accesstoken from storage - $cookies
    var access_token = $cookies.put('access_token');
    console.log('access_token ' + access_token);
    return access_token;
  }
  // This function will call all listeners (callbacks) and notify them that new access token is available
  // This is used to notify the web socket that new access token is available
  function notifySubscribersNewAccessToken(accessToken) {
    angular.forEach(subscribers, function(subscriber) {
      subscriber(accessToken);
    });
  }
  // Subscribe to this service. Be notifyed when access token is renewed
  function subscribe(callback) {
    subscribers.push(callback);
  }
}

和在config(app.js)

config.$inject = ['$stateProvider', '$urlRouterProvider', '$httpProvider'];
function config($stateProvider, $urlRouterProvider, $httpProvider) {
  // Push httpRequestInterceptor
  // $httpProvider.interceptors.push('httpRequestInterceptor');
  //Intercept all http requests
  $httpProvider.interceptors.push(['$injector', '$q', "AuthorizationTokenService", "$cookies", function ($injector, $q, AuthorizationTokenService, $cookies) {
    var cachedRequest = null;
    return {
      request: function (config) {
        //If request if for API attach Authorization header with Access Token
        if (config.url.indexOf("api") != -1) {
          // var accessToken = AuthorizationTokenService.getLocalAccessToken();
          console.log('cookie ' + $cookies.get('access_token'));
          config.headers.Authorization = 'Bearer ' + $cookies.get('access_token');
        }
        return config;
      },
      responseError: function (response) {
        switch (response.status) {
          // Detect if reponse error is 401 (Unauthorized)
          case 401:
          // Cache this request
          var deferred = $q.defer();
          if(!cachedRequest) {
            // Cache request for renewing Access Token and wait for Promise
            cachedRequest = AuthorizationTokenService.refreshAccessToken();
          }
          // When Promise is resolved, new Access Token is returend 
          cachedRequest.then(function(accessToken) {
            cachedRequest = null;
            if (accessToken) {
              // Resend this request when Access Token is renewed
              $injector.get("$http")(response.config).then(function(resp) {
                // Resolve this request (successfully this time)
                deferred.resolve(resp);
              },function(resp) {
                deferred.reject();
                console.log('success: refresh token has expired');
              });
            } else {
              // If any error occurs reject the Promise
              console.log('error: refresh token has expired');
              deferred.reject();
            }
          }, function(response) {
            // If any error occurs reject the Promise
            cachedRequest = null;
            deferred.reject();
            return;
          });
          return deferred.promise;
        }
        // If any error occurs reject the Promise
        return $q.reject(response);
      }
    };
  }]);
}

service & config ,我尝试实现基于Dual 401的重定向用户(平均刷新令牌也会过期并以401响应)。

我还尝试了多个后代401条件的尝试,但这也不正常。(如下)

responseError: function (response) {
  // Detect if reponse error is 401 (Unauthorized)
  if (response.status === 401) {
    // Cache this request
    var deferred = $q.defer();
    if(!cachedRequest) {
      // Cache request for renewing Access Token and wait for Promise
      cachedRequest = AuthorizationTokenService.refreshAccessToken();
    }
    // When Promise is resolved, new Access Token is returend 
    cachedRequest.then(function(accessToken) {
      cachedRequest = null;
      if (response.status === 401) {
        console.log('refresh token also expired');
        $location.path('/login');
      } else {
        // Resend this request when Access Token is renewed
        $injector.get("$http")(response.config).then(function(resp) {
          // Resolve this request (successfully this time)
          deferred.resolve(resp);
        },function(resp) {
          deferred.reject();
          console.log('success: refresh token has expired');
        });
      }
    }, function(response) {
      // If any error occurs reject the Promise
      cachedRequest = null;
      deferred.reject();
      return;
    });
    return deferred.promise;
  }
}

基于上述代码,请指导我我在做错了什么,或者也许登录/实现可能有问题。无论哪种情况,请帮助我。谢谢

我设法简单地使用以下代码来解决此问题;

config (app.js)

// Cache this request
var deferred = $q.defer();
if(!cachedRequest) {
    // Cache request for renewing Access Token and wait for Promise
    cachedRequest = AuthorizationTokenService.refreshAccessToken();
} else {
    // this is where it checks for request token expiry
    do_logout();
}

相关内容

  • 没有找到相关文章

最新更新