首页 文章

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

提问于
浏览
37

在PHP 3.0 SDK中,没有 getSession() 或来自Facebook api外部的任何会话处理 . 根据 this blog entrythis bug report ,几天前facebook的开发者也以某种方式更新了JavaScript sdk .

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

但是,我不知道这是否真的会影响我的问题 . 就像在 this question's answer 中一样,我正在使用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);
    }
}

问题

测试时一切都很好看 . 仅在发生错误时: the first time 设置权限后 . 现在,由于应用程序处于联机状态,似乎每个第二个用户平均发生错误

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

有错误:

An active access token must be used to query information about the current user.

问题

那为什么会这样呢?调试非常困难,因为错误似乎只发生在用户第一次进入应用程序时,在应用程序身份验证和访问令牌更改后 . 即便这样也不会每次都发生 . 我应该如何使用新的PHP SDK处理会话和访问令牌?

任何帮助都会非常感激!

编辑

我发现在iFrame中有一些IE问题与cookies / session有关 . 正如 in this blog post 所见 . 有了这个提示和一些进一步的研究,我在我的引导程序中添加了以下几行:

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)) {
    // get user data
}

if ((is_object($this->user) && $this->user->fbId == '') || $this->user === false || is_null($this->user)) {
    // get user data
}

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

此外,我添加了一个try / catch块,以查看我的应用程序中某个地方是否抛出了Facebook OAuthException . 如果是这种情况,我会将 top location 重定向到Facebook页面和标签以获得 new signed request . 虽然这可能有助于解决此问题,但我想阻止我的应用程序重定向用户 .

编辑3

经过几天激烈的调试和记录,我发现,来自 FB.ui permissions.request method$_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;
}

5 回答

  • 5

    嗨,我遇到了同样的麻烦似乎我已经解决了它看着JS API并重定向到PHP-SDK登录页面,如果用户信息是可读的

    例:

    <script language="JavaScript">
    
    function check_fb_status(){
        FB.api('/me', function(response){
         if(response.name) window.location='<?php echo $facebook->getLoginUrl(); ?>';
         else check_fb_status();
        });
    }
    
    check_fb_status();
    
    </script>
    

    如果脚本成功加载了登录页面,并且用户已被JS和PHP SDK识别;)

  • 10

    对于初学者,我会调试一下 . 记录请求的内容 . 什么存储在$ _SESSION中,$ _REQUEST传递了什么 . 另外,检查它是否是浏览器问题(无论浏览器是否发生,或者是否有模式?)

    但是,由于修复IE(P3P Headers )中的cookie问题有帮助,我的猜测是有一些浏览器,否认第三方cookie . 据我所知,Safari和Opera的某些版本默认情况下会这样做 . 此外,此错误表明没有提供 access_token ,而不是无效或过期 .

    您可以通过禁用第三方cookie(例如using about:config in firefox),取消对应用程序的授权(使用Facebook Privacy settings底部的"Apps and websites"部分),删除cookie(与画布URL相关)然后启动应用程序来测试 .

    顺便说一句,即使它应该,Facebook总是有可能不返回访问令牌,如described in bug 17236

  • 2

    我的解决方案

    好吧,因为我所做的一切只是一个解决方法,直到新的JS SDK出现,似乎没有最佳实践 . 将 session.use_trans_sid 设置为1并添加P3P标头有助于克服IE iFrame cookie问题(请参阅我的第一次编辑) . 经过几天的大量调试后我发现,FB.ui的 permission_request 每次都不会发送新的访问令牌(<5%) .

    如果发生这种情况,就会出现问题 . 但这件小事让我发疯 . 由于这种情况很少发生,我可以将用户重定向回facebook选项卡以获取新的签名请求 . 有了新的JS SDK,希望这不会再发生了 .

    更新:最终解决方案

    我监督过一件小事,可以在这里找到解决方案:FB is not defined problem
    我没 load the JS SDK asynchronously !这解释了一切 . 有时all.js文件加载速度不够快,所以有一个JS错误 . 因此,权限对话框和JS验证都不起作用并发送了一个空的#session输入值 .

  • 0

    仅供参考,Facebook大约2小时前发布了PHP SDK的更新,如果您使用JavaScript SDK在客户端上创建会话,则会增加对新cookie格式的支持 . 更新可以在Facebook PHP-SDK GitHub repo找到 .

  • 1

    我现在正在使用 PHP SDK 3.x 没有任何问题 .

    类作者Naitik删除了 getSession() 函数,现在如果您想知道用户是否经过身份验证,请使用 getUser() .

    对于Access令牌,它非常简单,使用此函数 getAccessToken() ,您将获得访问令牌以进行 Graph or Rest API 调用 .

    $user = $facebook->getUser();
    
    if ($user) {
    //USER Logged-In
    }
    else {
    //USER not Logged-In
    }
    
    //TO GET ACCESS TOKEN
    $access_token = $facebook->getAccessToken();
    
    
    //MAKE AN API CALL WITH IT
    $user_info = $facebook->api('me?fields=id,name,first_name,last_name&access_token='.$access_token);
    

相关问题