2

私はAngularが初めてです。Angular アプリでトークン認証を使用しています。HTTP インターセプターを使用して、バックエンドが 401 を返すタイミングを確認し、更新トークンを使用してログインします。

myapp.config(...)
...
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector) {
  var sessionRecoverer = {
    responseError: function(response) {
      // Session has expired
      if (response.status === 401) {
        var $http = $injector.get('$http');
        var deferred = $q.defer();
        var $auth = $injector.get('$auth');

        $auth.login({
          refresh_token: ????,
          grant_type: 'refresh_token',
          event_client: 'client',
          client_id: 'id'
        });

        // When the session recovered, make the same backend call again and chain the request
        return deferred.promise.then(function() {
          return $http(response.config);
        });
      }
      return $q.reject(response);
    }
  };
  return sessionRecoverer;
}]);

これで、refresh_token はログイン コントローラー (API バックエンドから取得) から取得されます。したがって、コントローラーはそれを何らかの方法でインターセプターに渡す必要があります。問題は、インターセプターが構成ブロックにあるため、サービスや値などがないことです-プロバイダーのみ。ただし、プロバイダーはコントローラーに注入できません。コントローラーから app.config にデータを渡す方法はありますか? そうでない場合、回避策はありますか?インジェクターは app.config 以外の場所に配置できますか?

4

1 に答える 1

1

はい、次のように簡単に実行できます。

    myapp.config(...)
    ...
    $httpProvider.interceptors.push(['$q', '$injector', function($q, $injector, TokenFactory) {
      var sessionRecoverer = {
        responseError: function(response) {
          // Session has expired
          if (response.status === 401) {
            var $http = $injector.get('$http');
            var deferred = $q.defer();
            var $auth = $injector.get('$auth');

            $auth.login({
              refresh_token: TokenFactory.getRefreshToken(),
              grant_type: 'refresh_token',
              event_client: 'client',
              client_id: 'id'
            });

            // When the session recovered, make the same backend call again and chain the request
            return deferred.promise.then(function() {
              return $http(response.config);
            });
          }
          return $q.reject(response);
        }
      };
      return sessionRecoverer;
    }]);

あなたが言うように、ブロック構成はプロバイダーのみを注入できますが、インターセプター自体はファクトリーであるため、必要に応じて更新トークンを返すメソッドを提供する必要がある TokenFactory と呼ばれるファクトリーなど、他のファクトリーを注入できます。

編集

refresh_token がバックエンドから来るもので、ログイン コントローラーから TokenFactory 内に値を設定したい場合は、次のようにして factory と controller を実装できます。

myapp.factory('TokenFactory',function(){

  var currentRefreshToken;

  return {
    setRefreshToken: function(token){
      currentRefreshToken = token;
    },
    getRefreshToken: function(){
      return currentRefreshToken:
    }
  };
});

myapp.controller('MyLoginCtrl',function($scope,TokenFactory,$http){

  $scope.login = function(){
    $http.post('http://myapp.com/refreshtoken',$scope.credentials)
      .then(TokenFactory.setRefreshToken)
      .then(function(){ /* ... */})
      .catch(function(err){ console.error(err) })
    ;
  };

});

データの永続性

トークンを持続させたい場合は、 を使用するファクトリを作成し、LocalStorage HTML5 APIそれを で使用できますTokenFactory

myapp.factory('TokenFactory',function(LocalStorage){

  // load the value from localstorage (hard disk) on app starts
  var currentRefreshToken = LocalStorage.get('myapp.currentRefreshToken');

  return {
    setRefreshToken: function(token){
      currentRefreshToken = token; // save value in RAM
      LocalStorage.set('myapp.currentRefreshToken',token); // and sync the localstorage value
    },
    getRefreshToken: function(){
      return currentRefreshToken; // quick access to the value from RAM
    }
  };
});

myapp.factory('LocalStorage',function($window) {

    var localStorage = {};

    localStorage.set = function(key, value) {
        $window.localStorage[key] = value;
    };
    localStorage.get = function(key, defaultValue) {
        return $window.localStorage[key] || defaultValue;
    };
    localStorage.setObject = function(key, value) {
        $window.localStorage[key] = JSON.stringify(value);
    };
    localStorage.getObject = function(key) {
        return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? {} : JSON.parse($window.localStorage[key]);
    };
    localStorage.setArray = function(key, array){
        if (!array.length) {
            console.debug(array);
            $window.localStorage[key] = '[]';
        } else{
            this.setObject(key, array);                    
        }
    };
    localStorage.getArray = function(key){
        return (!$window.localStorage[key] || $window.localStorage[key] === undefined) ? [] : JSON.parse($window.localStorage[key]);
    };
    localStorage.exportAsFile = function(key, fileName){        
        var data = [$window.localStorage[key]] || ['{}'];
        var blob = new Blob(data,{type:'application/json;charset=utf-8'});
        $window.saveAs(blob,fileName);
    };
    return localStorage;
});
于 2015-11-12T16:21:48.493 に答える