Вход в Google - выключение при обновлении
У меня есть следующая настройка:
.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) {
}]);
В основном, что происходит, когда я вхожу в систему с помощью кнопки входа в Google, он подписывается, а googleService.getProfile()
говорит, что я вошел.
Однако, если я обновляю страницу, googleService.isSignedIn()
возвращает false.
Может ли кто-нибудь увидеть проблему, почему он будет возвращать false? Есть ли что-то еще, что мне нужно сделать, чтобы убедиться, что Google помнит меня?
Ответы
Ответ 1
Основная проблема заключается в том, что вы вызываете gapi.auth2.init()
снова и снова через googleService.load()
.
Мое предложение состоит в том, чтобы сохранить инициализацию promises для повторного использования, а не для ее создания много раз.
Вам также необходимо добавить условие для обработки токена с истекшим доступом.
.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 };
}
});
};
}])
Каждый из ваших методов обслуживания (isSignedIn
, signOut
и getProfile
) теперь возвращает обещание, которое разрешается только после инициализации API auth2
, однако это только когда-либо происходит один раз.
Например
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();
}
});
}];
Ответ 2
Вам нужно включить authenticated
в качестве зависимости в вашем контроллере cloud
. Кроме того, в вашем googleService
в вашем обработчике успеха вы должны defer.resolve()
после выполнить localStorage['access_token'] = p.access_token;
и $rootScope.profile = p.profile;
Ответ 3
Привет Вносите следующие изменения в свой код и дайте мне знать, если он работает.
.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) {
}]);