2017-02-23 229 views
10

登出後,我有以下設置:谷歌登錄 - 在刷新

.service('googleService', ['$q', function ($q) { 
    var self = this; 

    this.load = function(){ 
     var deferred = $q.defer(); 
     gapi.load('auth2', function(){ 
      var auth2 = gapi.auth2.init(); 
      auth2.then(function(){ deferred.resolve(); }); 
      addAuth2Functions(auth2); 
     }); 
     return deferred.promise; 
    }; 

    function addAuth2Functions(auth2) { 

     self.isSignedIn = function(){ 
      return auth2.isSignedIn.get(); 
     } 

     self.signOut = function(){ 
      var deferred = $q.defer(); 
      auth2.signOut().then(deferred.resolve, deferred.reject); 
      return deferred.promise; 
     }; 

     self.getProfile = function() { 
      if(auth2.isSignedIn.get()) return { signed_in: true, access_token: auth2.currentUser.get().Zi.id_token,profile: auth2.currentUser.get().getBasicProfile() }; 
      else return { signed_in: false }; 
     } 

    } 

}]) 

.config(function($stateProvider, $urlRouterProvider, $locationProvider) { 

    $locationProvider.html5Mode(true); 
    $urlRouterProvider.otherwise('/cloud'); 

    var guest = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

     var deferred = $q.defer(); 

     googleService.load().then(function(){ 
      $q.when(googleService.isSignedIn()).then(function(r){ 
       if(r) deferred.reject(); 
       else deferred.resolve(); 
      }) 
     }); 

     return deferred.promise; 
    }]; 

    var authenticated = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

     var deferred = $q.defer(); 

     googleService.load().then(function(){ 
      $q.when(googleService.getProfile()).then(function(p) { 
       if(p.signed_in) { 
        deferred.resolve(); 
        localStorage['access_token'] = p.access_token; 
        $rootScope.profile = p.profile; 
       } else deferred.reject(); 
      }) 
     }); 

     return deferred.promise; 
    }]; 

    $stateProvider 

    .state('login', { 
     url: '/', 
     views: { 'main': { templateUrl: 'pages/templates/login.html', controller: 'login' } }, 
     resolve: { authenticated: guest } 
    }) 

    .state('cloud', { 
     url: '/cloud', 
     views: { 'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' } }, 
     resolve: { authenticated: authenticated } 
    }) 

}) 

.controller('login', ['$rootScope', '$scope', '$q', '$state', 'googleService', function ($rootScope, $scope, $q, $state, googleService) { 
    $scope.options = { 'onsuccess': function(response) { $state.go('cloud'); } } 
}]) 

.controller('cloud', ['$rootScope', '$scope', '$timeout', '$http', '$httpParamSerializerJQLike', function ($rootScope, $scope, $timeout, $http, $httpParamSerializerJQLike) { 

}]); 

基本上所發生的事情是,當我在使用按鈕,在谷歌網友實拍,它簽署並googleService.getProfile()說我我登錄。

但是,如果我刷新頁面,googleService.isSignedIn()返回false。

任何人都可以看到一個問題,爲什麼它會返回false?還有什麼我需要做的,以確保谷歌記得我嗎?

+2

你可以提供一個小提琴? –

+1

也許我錯過了一些東西,但我沒有看到你曾經訪問過本地存儲令牌'localStorage.getItem('access_token')'。您需要檢查該令牌是否存在,以及它是否仍然有效,以便您在刷新時進行身份驗證。此外,您可能需要考慮使用cookie,因爲cookie會提供一個可以不斷重置的超時時間。請參閱:http://stackoverflow.com/questions/244882/what-is-the-best-way-to-implement-remember-me-for-a-website –

+0

我在認證的「解決方案」中訪問它,但我可以做錯了@ td-edge – bryan

回答

2

你的主要問題似乎是,你通過調用googleService.load()gapi.auth2.init()一遍又一遍。

我的建議是存儲重新使用的初始化承諾,而不是多次創建它。

您還需要添加一個條件來處理過期的訪問令牌。

.service('googleService', ['$q', function ($q) { 
    const auth2InitPromise = $q(function(resolve) { 
     gapi.load('auth2', function() { 
      var auth2 = gapi.auth2.init(); 
      auth2.then(function() { 
       resolve(); 
      }); 
     }) 
    }); 

    this.isSignedIn = function() { 
     return auth2InitPromise.then(function() { 
      return gapi.auth2.getAuthInstance().isSignedIn.get(); 
     }); 
    }; 

    this.signOut = function() { 
     return auth2InitPromise.then(function() { 
      const auth2 = gapi.auth2.getAuthInstance(); 
      return $q(function(resolve, reject) { 
       auth2.signOut().then(resolve, reject); 
      }); 
     }); 
    }; 

    this.getProfile = function() { 
     return this.isSignedIn().then(function(isSignedIn) { 
      if (isSignedIn) { 
       const currentUser = gapi.auth2.getAuthInstance().currentUser.get(); 
       const authResponse = currentUser.getAuthResponse(); 
       return $q.when(authResponse.expires_at > Date.now() ? authResponse : currentUser.reloadAuthResponse()).then(function(ar) { 
        return { 
         signed_in: true, 
         access_token: ar.id_token, 
         profile: currentUser.getBasicProfile() 
        }       
       }); 
      } else { 
       return { signed_in: false }; 
      } 
     }); 
    }; 

}]) 

您的每個服務的方法(isSignedInsignOutgetProfile)現在返回一個承諾,只有解決一旦auth2 API然而這個初始化永遠只發生一次了。


例如

var authenticated = ['$q', '$rootScope', '$window', 'googleService', function ($q, $rootScope, $window, googleService) { 
    return googleService.getProfile().then(function(p) { 
     if (p.signed_in) { 
      $window.localStorage.setItem('access_token', p.access_token); 
      $rootScope.profile = p.profile; 
      return true; // resolvers should always resolve with something 
     } else { 
      return $q.reject(); 
     } 
    }); 
}]; 
+0

乾淨的解決方案! – Kalyan

+0

這也是真的 –

+0

謝謝菲爾,乍一看這似乎很好用!謝謝你的解釋 – bryan

3

您需要在您的cloud控制器中包含authenticated作爲依賴項。此外,在你在你的成功處理程序googleService應該defer.resolve()你你做localStorage['access_token'] = p.access_token;$rootScope.profile = p.profile;

+0

很確定所有的解析器都被解析*無論它們是否包含在控制器參數中。 – Phil

+0

這不適用於角色I的工作版本,1.3.x. –

+0

你會在這裏看到它確實是真的〜http://plnkr.co/edit/Y4N6ropCXTjEHvJQ13Au?p=preview – Phil

0

嗨執行以下更改代碼,讓我知道,如果它的工作原理。

.service('googleService', ['$q', function ($q) { 
    var self = this; 

    this.load = function(){ 
     gapi.load('auth2', callback);    
    }; 

    function callback(){ 
     var deferred = $q.defer(); 
     gapi.auth2.init()//use your client credentials here 
     .then(function(){ deferred.resolve(); }); 
     return deferred.promise; 
    } 


    self.isSignedIn=function (auth2){ 
     return auth2.isSignedIn.get(); 
    }; 

    self.signOut =function(auth2){ 
     var deferred = $q.defer(); 
     auth2.signOut().then(deferred.resolve, deferred.reject); 
     return deferred.promise; 
    }; 

    self.getProfile= function(auth2) { 
     if(auth2.isSignedIn.get()) return { signed_in: true, access_token: auth2.currentUser.get().Zi.id_token,profile: auth2.currentUser.get().getBasicProfile() }; 
     else return { signed_in: false }; 
    };  


}]) 

    .config(function($stateProvider, $urlRouterProvider, $locationProvider) { 

     $locationProvider.html5Mode(true); 
     $urlRouterProvider.otherwise('/cloud'); 



     var guest = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

      var deferred = $q.defer(); 
      googleService.load().then(function(){ 
       googleService.isSignedIn(gapi.auth2.getAuthInstance()).then(function(r){ 
        if(r) deferred.reject(); 
        else deferred.resolve(); 
       }); 
      }); 



      return deferred.promise; 
     }]; 

     var authenticated = ['$q', '$rootScope', '$stateParams', 'googleService', function ($q, $rootScope, $stateParams, googleService) { 

      var deferred = $q.defer(); 

      googleService.load().then(function(){ 
       googleService.getProfile(gapi.auth2.getAuthInstance()).then(function(p) { 
        if(p.signed_in) { 
         deferred.resolve(); 
         localStorage['access_token'] = p.access_token; 
         $rootScope.profile = p.profile; 
        } else deferred.reject(); 
       }); 
      });    

      return deferred.promise; 
     }]; 

     $stateProvider 

     .state('login', { 
      url: '/', 
      views: { 'main': { templateUrl: 'pages/templates/login.html', controller: 'login' } }, 
      resolve: { authenticated: guest } 
     }) 

     .state('cloud', { 
      url: '/cloud', 
      views: { 'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' } }, 
      resolve: { authenticated: authenticated } 
     }) 

    }) 

    .controller('login', ['$rootScope', '$scope', '$q', '$state', 'googleService', function ($rootScope, $scope, $q, $state, googleService) { 
     $scope.options = { 'onsuccess': function(response) { $state.go('cloud'); } } 
    }]) 

    .controller('cloud', ['$rootScope', '$scope', '$timeout', '$http', '$httpParamSerializerJQLike', function ($rootScope, $scope, $timeout, $http, $httpParamSerializerJQLike) { 

    }]); 
+1

不解決使用auth實例的承諾,它會創建無限循環的promise解決方案(愚蠢的Google API) – Phil

+0

感謝您指出它。我已更新我的代碼 – Kalyan

+0

沒問題。我在那個上浪費了太多時間。 – Phil