谷歌+;使用JavaScript回调问题登录

谷歌+;使用JavaScript回调问题登录,javascript,callback,google-api,google-plus,google-oauth,Javascript,Callback,Google Api,Google Plus,Google Oauth,我正在开发一个功能,允许用户使用他们的谷歌帐户登录我的网站 我的代码基于(其他signIn()选项位于meta标记中) 当我调用login()时,会出现一个Google弹出窗口,我批准了应用程序的条款,一切正常 但回调被调用两次: 第一种情况:如果我从未批准应用程序权限,则在弹出窗口打开时以及我批准权限时将调用回调。所以它会写“Error”和“ok” 第二种情况:如果我已经批准了权限,它会写两次“OK” 我在signIn()函数中添加了选项'approvalprompt':'force'。回

我正在开发一个功能,允许用户使用他们的谷歌帐户登录我的网站

我的代码基于(其他signIn()选项位于meta标记中)

当我调用login()时,会出现一个Google弹出窗口,我批准了应用程序的条款,一切正常

但回调被调用两次:

  • 第一种情况:如果我从未批准应用程序权限,则在弹出窗口打开时以及我批准权限时将调用回调。所以它会写“Error”和“ok”
  • 第二种情况:如果我已经批准了权限,它会写两次“OK”
我在signIn()函数中添加了选项
'approvalprompt':'force'
。回调函数不再被调用两次,但它会强制用户批准应用程序的权限,即使之前已批准。所以它不是用户友好的

是否有一种友好的用户方式可以一次性批准应用程序的权限,而无需两次回调


多谢各位

尝试在某个局部变量中注册第一个调用,然后处理它

此快速解决方案可帮助我:

function login() {
  var initializedGoogleCallback = false
  gapi.auth.signIn({
    'callback': function (authResult) {
       if (!initializedGoogleCallback) {
         // after first call other will be ignored
         initializedGoogleCallback = true;
         if (authResult['status']['signed_in']) {
           console.log('Okay');
         } else {
           console.log('Error');
         }
       }
    }
  });
}
您还可以在调用gapi.auth.sign之前添加以下代码

window.removeEventListener('load')

我面临着同样的问题:如果用户已经授予了权限,则会调用两次signin回调;局部变量方法(InitializeGoogleCallback)对我不起作用,因为它只在用户已经被授予访问权限时调用回调一次,但如果用户是新用户,它不会调用回调。 经过一番研究(我特别是使用g+auth挖掘网站),我注意到他们都使用了
'approvalprompt':'force'
,并且他们已经授予用户每次重新批准“脱机访问”策略的权限。 即使是我在安装我的应用程序()时所遵循的谷歌示例,即使它没有提到它,它也使用了“force”参数。
目前,如果您想使用javascript流(这意味着如果您需要个人风格的登录按钮),它似乎是唯一的解决方案。

这是页面级配置的有意计划!它出现在页面中会导致在Javascript加载完成时触发回调。您应该在代码中为此做准备

在收到回调之前不要显示登录按钮-如果
authResult['status']['signed\u in']==true
,则将用户视为已登录(设置会话等,无论您通常做什么)。如果为false,则显示该按钮

function signinCallback(authResult) {
  if (authResult['status']['signed_in']) {
    document.getElementById('signinButton').setAttribute('style', 'display: none');
    // Do sign in stuff here!
  } else {
    document.getElementById('signinButton').setAttribute('style', 'display: block');
  }
}

如果可以,我将避免使用批准提示强制

我终于找到了解决办法;我不知道这是正确的方法还是我只是在作弊,但我是这样做的:

首先是页面中的一些脚本(我使用的是bootstrap+jquery)

function render(){
//我没有用它,但还是保留了下来
}
var i;
//通过单击链接或按钮(“使用g+登录”按钮)调用函数
函数gp_login(){
i=0;
$('#alertbox')。删除();
var附加参数={
“回调”:signinCallback,
/*“approvalprompt”:“force”最终被删除*/
};
$('gp login')。按钮('loading');
gapi.auth.signIn(附加参数);
}
函数signinCallback(authResult){//my回调函数
var电子邮件=“”;
var给定_名称=“”;
如果(authResult['status']['signed_in']){//获取一些用户信息
load('oauth2','v2',function(){
gapi.client.oauth2.userinfo.get().execute(函数(resp){
email=resp.email;//获取用户电子邮件
给定名称=resp.给定名称;//获取用户电子邮件
family_name=相应的family_name;
id=各自的id;

if(i我在这里面临同样的问题,但我正在通过按钮单击处理程序调用gapi.auth.signIn()。回调仍然被调用两次。我注意到两个authResult对象之间的一件事是authResult.status.method在第一次调用中是“自动”(在弹出窗口出现之前)并在窗口因先前授权而自动关闭后的第二次呼叫中“提示”


我现在正在探索的解决方案是忽略自动实例,只处理回调的提示实例。由于“status”对象的文档中缺少详细信息,我不确定一旦我在Google内撤销权限,这将如何工作。

就像Drew Taylor的回答一样,以避免使用纯javascript符号的双重回调在解决方案中,您可以:


我认为自动方法的回调是由第一次登录时显示的底部欢迎栏触发的。

这是一个很好的解决方案,谢谢!但我仍然不知道为什么我们必须这样做,这就像“作弊”。可能是一个bug,或者我们只是不了解原因。我认为原因在谷歌js库中。但谷歌没有提供在新方法调用之前删除所有以前事件的正常方法。而且没有源js来完全理解原因,API也没有描述这一点。这对你来说是如何实现的?我也在考虑这样做。我是dea同样的问题,我最终实现了一个类似的“修复”,但有一个真/假变量。如果用户必须单击按钮才能触发回调,那么隐藏按钮如何帮助用户呢?隐藏按钮并不能修复双重回调问题。对于javascript方法,他们不必单击按钮才能触发回调-它将在添加到e DOM。如果使用页面级配置,它将在页面加载完成后立即触发。因此,流程将是:页面加载,回调启动,如果未登录显示按钮。可能我不理解其中的某些内容-。引用:您应该只使用用户启动的事件来触发此方法,例如单击,以便弹出窗口阻止程序不会阻止授权对话框打开。同样在示例中,onload只调用
render()
,这只是将eventListener添加到按钮。加载页面时不调用回调。因此,auth shou的弹出窗口
function signinCallback(authResult) {
  if (authResult['status']['signed_in']) {
    document.getElementById('signinButton').setAttribute('style', 'display: none');
    // Do sign in stuff here!
  } else {
    document.getElementById('signinButton').setAttribute('style', 'display: block');
  }
}
function render() {
    //I am not using it but kept anyway

 }
var i;
// Function called from a onClick on a link or button (the 'sign in with g+' button)
function gp_login() {
    i=0;
    $('#alertbox').remove();
    var additionalParams = {
     'callback': signinCallback,
     /*'approvalprompt': 'force' finally removed*/
    };
    $('#gp-login').button('loading');
    gapi.auth.signIn(additionalParams); 
}

function signinCallback(authResult) { //my callback function
        var email='';
        var given_name='';
        if (authResult['status']['signed_in']) { //get some user info
            gapi.client.load('oauth2', 'v2', function() {
                gapi.client.oauth2.userinfo.get().execute(function(resp){
                    email = resp.email; //get user email
                    given_name = resp.given_name; //get user email
                    family_name=resp.family_name;
                    id=resp.id;
                    if (i<2) { //execute the doLogin just one time (my cheat)
                        doLogin(email,given_name,family_name,id); //dologin does my logic with an ajax call to signup/register user to my site
                    }
                    i=2;
                });
            });
        } else {
        // Update the app to reflect a signed out user
      }

}
if (authResult["status"]["method"] == "PROMPT") {...}