你能从其他FB方法(如FB.getLoginStatus)的回调中调用FB.login而不触发弹出窗口阻止程序吗



我正在尝试使用FB JavaScript SDK设置一个非常基本的身份验证逻辑流,以在执行操作之前检查用户的登录状态和权限(如果没有权限,则提示用户使用权限登录)。

  1. 用户在我网站的文本区键入一条消息,发布到他们的Facebook订阅源,然后点击我网站上的"发布到Facebook"按钮
  2. 响应点击,我用FB.getLoginStatus检查用户的登录状态
  3. 在对FB.getLoginStatus的回调中,如果用户未登录,则提示他们登录(FB.login
  4. 在对FB.login的回调中,我需要确保他们有正确的权限,所以我会调用FB.api('/me/permissions')——如果他们没有,我会再次提示他们登录(FB.login

我遇到的问题是,每当我试图在其他FB方法的回调中调用FB.login时,浏览器似乎会失去对执行来源(点击)的跟踪,从而阻止弹出窗口。我想知道我是否错过了在检查用户状态后提示用户登录的方法,而浏览器不会误以为这不是用户启动的弹出窗口?

我现在已经回到了只需要先打FB.login()就可以了。然而,这种方法不希望出现的副作用是,如果用户已经使用权限登录,而我仍在调用FB.login,则验证弹出窗口将在继续之前立即打开和关闭,尽管这是有效的,但看起来相当bug。

在做某事之前检查用户的登录状态和权限似乎是一个常见的流程,所以我觉得我错过了一些东西。下面是一些示例代码。

<div onclick="onClickPostBtn()">Post to Facebook</div>
<script>
// Callback to click on Post button.
function onClickPostBtn() {
    // Check if logged in, prompt to do so if not.
    FB.getLoginStatus(function(response) {
        if (response.status === 'connected') {
            checkPermissions(response.authResponse.accessToken);
        } else {
            FB.login(function(){}, {scope: 'publish_stream'})
        }
    });
}
// Logged in, check permissions.
function checkPermissions(accessToken) {
    FB.api('/me/permissions',
        {'access_token': accessToken},
        function(response){
            // Logged in and authorized for this site.
            if (response.data && response.data.length) {
                // Parse response object to check for permission here...
                if (hasPermission) {
                    // Logged in with permission, perform some action.
                } else {
                    // Logged in without proper permission, request login with permissions.
                    FB.login(function(){}, {scope: 'publish_stream'})
                }
            // Logged in to FB but not authorized for this site.
            } else {
                FB.login(function(){}, {scope: 'publish_stream'})
            }
        }
    );
}
</script>

我遇到的问题是,每当我试图在其他FB方法的回调中调用FB.login时,浏览器似乎会失去对执行来源(点击)的跟踪,从而阻止弹出窗口。

他实际上并不是"迷失方向"——这是一个完全不同的执行上下文,因为FB方法异步工作。单击发生在一个执行上下文中,该上下文早就不存在了,并且在执行回调函数时已完成。

您可以在页面加载之前检查权限。我想,当用户在你的网站上时,他所获得的权限不太可能发生变化——至少对于一个"正常"用户来说,他不会试图破坏你的应用程序,看看它会有什么反应。(尽管可能有一些用例不能肯定地说这一点。)

如果这导致信息中缺少必要的权限,请致电FB.login,点击按钮请求此权限。在FB.login回调中,如果你想确定的话,你可以再次检查权限-如果权限仍然没有被授予,那么,我建议提醒用户注意这一事实,也许再告诉他为什么有必要这样做-然后他必须再次单击启动整个操作的按钮。

如果权限还可以,那么您可以调用API来实际发布。为了真正确定和安全起见……在API调用的回调中,您可以再次检查成功或错误,如果出现错误,请查明是否是由于缺少权限造成的——如果是,请返回正方,告诉用户权限是必要的,并让他通过单击按钮重新开始整个过程…

我有另一个解决方案,可以更优雅地检查用户是否有

  • A) 已登录FB
  • B) 正确的权限

简而言之,对于a),您需要"提醒"用户他没有登录,而不是"回调"Fb.login。然后您的页面应该刷新,并在刷新期间处理登录过程。

但是,对于B)权限,您可以使用fb.ui方法(使用display:iframe)请求权限(通过回调),而不是使用fb.login请求权限。使用display:iframe应该可以避免弹出窗口阻塞程序的麻烦。

请参阅以下修改后的代码:

<div onclick="onClickPostBtn()">Post to Facebook</div>
<script>
// Callback to click on Post button.
function onClickPostBtn() {
    // Check if logged in, prompt to do so if not.
    FB.getLoginStatus(function(response) {
        if (response.status === 'connected') {
            checkPermissions(response.authResponse.accessToken);
        } else {
            //Don't call FB.login because this results in popup blocker.
            //FB.login(function(){}, {scope: 'publish_stream'})
            //Instead, just alert user that "YOu are not connected to FB", and then refresh the page (which should theoreticalyl handle the logging aspect)
        }
    });
}
// Logged in, check permissions.
function checkPermissions(accessToken) {
    FB.api('/me/permissions',
        {'access_token': accessToken},
        function(response){
            // Logged in and authorized for this site.
            if (response.data && response.data.length) {
                // Parse response object to check for permission here...
                if (hasPermission) {
                    // Logged in with permission, perform some action.
                } else {
                    //Don't use FB.login to request permissions. Instead use a FB.ui ({method:'permissions.request'} with "display" set to "iframe"
                    //FB.login(function(){}, {scope: 'publish_stream'})
                    FB.ui(
                    {
                         method: 'permissions.request',
                         'perms': 'publish_stream,WHATEVER_PERMISSIONS',
                         'display': 'iframe' //THIS IS IMPORTANT TO PREVENT POPUP BLOCKER
                    },
                    function(response) {
                        //Do action if permissions add success other wise prompt error adding permissions.
                    }
                }
            // Logged in to FB but not authorized for this site.
            } else {
                //Don't call FB.login because this results in popup blocker.
                //FB.login(function(){}, {scope: 'publish_stream'})
                //Instead, just alert user that "YOu are not connected to FB", and then refresh the page (which should theoreticalyl handle the logging aspect)
            }
        }
    );
}
</script>

最新更新