页面刷新后如何注销用户?

How to sign out a user after page refresh?

我正在关注 Google's guide 退出用户。

考虑到刷新页面后gapi.auth2将是未定义的,我这样做:

if (gapi.auth2) {
    var auth2 = gapi.auth2.getAuthInstance();
    auth2.signOut();
} else {
    gapi.load('auth2', function () {
        gapi.auth2.init({
            client_id: 'myAppID',
            cookiepolicy: 'single_host_origin'
        }).signOut();
    });
}

但我在 else 块中得到 uncaught exception: This method can only be invoked after the token manager is started

我也曾尝试将 auth 实例存储在本地存储中,但这样做会导致在对其进行字符串化时出现一些循环对象值错误。

一个可能的解决方案是

document.location.href = "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=myUrl";

但是,除了进行不必要的重定向之外,这不仅会影响用户登录我的应用程序,还会影响他登录的所有 Google 服务。

是否有不同的方法?

我没有检索 GoogleAuth 库的单例并在我的登录页面控制器中设置客户端,而是不得不在 index.html 文件中初始化它:

<script src="https://apis.google.com/js/api:client.js?onload=start" async defer></script>
<script>
    function start() {
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
            client_id: 'myAppID',
            cookiepolicy: 'single_host_origin'
        });
      });
    }
</script>

这解决了注销问题。但是,如果登录页面被刷新,其控制器逻辑将在 gapi.auth2 定义之前执行,并且无法将点击处理程序成功附加到登录按钮。

为了避免这种情况——尽管这不是一个优雅的解决方案——我使用 $interval 等待 gapi.auth2 初始化:

waitForAuth2Initialization = $interval(function () {
    console.log("Checking...");
    if (!gapi.auth2)
        return;
    console.log("Ok, gapi.auth2 is not undefined anymore");
    var auth2 = gapi.auth2.getAuthInstance();
    // Attach signin
    auth2.attachClickHandler...

    $interval.cancel(waitForAuth2Initialization);
}, 50);

编辑: 另一种可能的解决方案是对控制器逻辑使用承诺回调以等待承诺得到解决,即直到 Google API 是完全加载并且 gapi.auth2 可以使用了。 可以通过以下方式实现:

<script src="https://apis.google.com/js/api:client.js?onload=start" async defer></script>
<script>
    gapiPromise = (function () {
        var deferred = $.Deferred();
        window.start = function () {
            deferred.resolve(gapi);
        };
        return deferred.promise();
    }());
    auth2Promise = gapiPromise.then(function () {
        var deferred = $.Deferred();
        gapi.load('auth2', function () {
            auth2 = gapi.auth2.init({
                client_id: 'myAppID',
                cookiepolicy: 'single_host_origin'
            }).then(function () { 
                deferred.resolve(gapi.auth2); 
            });
        });
        return deferred.promise();
    });
</script>

然后在控制器中:

auth2Promise.then(function () {
    console.log("Ok, gapi.auth2 is not undefined anymore");
    var auth2 = gapi.auth2.getAuthInstance();
    // Attach signin
    auth2.attachClickHandler...
});

但是,这种方法的缺点是它比第一种使用 $interval.

的方法慢(附加点击处理程序的时间是第一种方法的两倍)

有一个更简单的方法,你只需要在调用 gapi 之后调用 .then 即可。auth2.init

gapi.load('auth2', function () {
   var auth2 = gapi.auth2.init({
       client_id: 'myAppID',
       cookiepolicy: 'single_host_origin'
   });
   auth2.then(function(){
        // this get called right after token manager is started
        auth2.signOut();
   });
});