如何正确处理Facebook PHP SDK 3.0中的会话和访问令牌?

7 浏览
0 Comments

如何正确处理Facebook PHP SDK 3.0中的会话和访问令牌?

在PHP 3.0 SDK中,没有getSession()或任何来自Facebook api外部的会话处理可用。几天前,Facebook的开发人员也以某种方式更新了JavaScript SDK,根据这篇博客文章这篇错误报告所述。

在过去几天里,托管的JS SDK中引入了一项变更,破坏了它与当前PHP SDK(2.x和3.x)之间的所有兼容性。同时使用JS和PHP SDK的开发人员可能会看到服务器端API失败。

然而,我不知道这是否真的影响到我的问题。就像在这个问题的答案中所述,我正在使用PHP检索OAuth对话框的访问令牌,并将新的访问令牌保存在会话中。

当前的解决方法

以下代码显示了我如何处理这些会话。 $_REQUEST['session']是OAuth对话框响应的内容。

if(isset($_REQUEST['session'])) {
    $response = json_decode(stripslashes($_REQUEST['session']), true);
    if(isset($response['access_token'])) {
        $this->api->setAccessToken($response['access_token']);
        $_SESSION['access_token'] = $this->api->getAccessToken();
    }
}
elseif(isset($_SESSION['access_token']) && ! isset($_REQUEST['signed_request'])) 
    $this->api->setAccessToken($_SESSION['access_token']);
elseif(isset($_REQUEST['signed_request'])) {
    Session::invalidate('fbuser');
    $_SESSION['access_token'] = '';
}

以下是我如何处理用户数据的方式:

try {
    $this->user = Session::getVar('fbuser');
    if ($this->user === false || is_null($this->user)) {
        $facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');
        $this->user = new FBUserModel(array('fbId' => $facebookUser['fbId'], ...));
        Session::setVar('fbuser', $this->user);
    }
}

问题

测试时一切看起来都很好。只有一次出现了错误:在设置权限后的第一次。现在,由于应用程序已经在线,似乎每隔两个用户就会出现错误。

$facebookUser = $this->api->api('me?fields=id,name,first_name,last_name');

报错信息为:

必须使用活动访问令牌来查询有关当前用户的信息。

问题

那么为什么会发生这种情况呢?很难调试,因为错误似乎只在用户第一次进入应用程序时发生,经过应用程序验证并更改访问令牌时。而且这并不是每次都发生。我应该如何正确处理会话和访问令牌以适应新的PHP SDK?

非常感谢任何帮助!

编辑

我发现在iFrame内部存在一些IE的cookie/会话问题。如这篇博客文章中所见。在得到这个提示和进一步的研究后,我在我的引导程序中添加了以下几行代码:

ini_set('session.use_trans_sid', 1);
header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');

现在好多了,但大约50个用户中有2个用户的信息在登陆页(身份验证)->表单->注册之间丢失。所以还有些问题我没解决。

编辑2

我将用户处理从以下代码进行了修改:

if ($this->user === false || is_null($this->user)) {
    // 获取用户数据
}

修改为

if ((is_object($this->user) && $this->user->fbId == '') || $this->user === false || is_null($this->user)) {
    // 获取用户数据
}

这似乎有点帮助。我认为主要问题出现在我的会话中的某个地方。

此外,我添加了一个try/catch块,以查看是否在我的应用程序中抛出了Facebook OAuthException。如果是这样,我将顶级位置重定向到Facebook页面和选项卡以获取新的签名请求。虽然这可能有助于解决这个问题,但我想避免我的应用程序不得不重定向用户。

编辑3

经过几天的密集调试和日志记录,我发现从FB.ui permissions.request方法传来的$_REQUEST['session']偶尔是空的。

以下是我如何处理它的方式:

这是我始终包含的内容:

FB.provide("UIServer.Methods", {'permissions.request': {size : {width: 575, height: 300}, url: 'connect/uiserver.php', transform : FB.UIServer.genericTransform}});

在表单提交时调用此函数。对我来说总是有效的,但是它仍然发送表单,尽管session == ''

function getPermission(form) {
    session = $('#' + $(form).attr('id') + ' input[name="session"]');
    if($(session).val() != '') {
        form.submit();
        return;
    }
    FB.ui({method: "permissions.request", "perms": 'user_photos'}, function callback(info){
        if(info.status=='connected' && info.session !== null) {
            $(session).val(JSON.stringify(info.session));
            form.submit();
        }
    });
    return;
}

0