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

在PHP 3.0 SDK中,没有getSession()或者Facebook API以外的任何会话处理。 根据这个博客条目这个错误报告 ,几天前Facebook的开发者也不知何故更新了JavaScript sdk。

在过去的几天里,一个更改被引入到托pipe的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); } } 

问题

testing时一切都很好。 只有一次发生错误: 第一次设置权限后。 现在,由于该应用程序是在线的,似乎错误发生在平均每个第二用户

 $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. 

那为什么会这样呢? debugging非常困难,因为错误似乎只发生在用户首次进入应用程序,应用程序authentication和访问令牌发生变化之后。 而且即使这样,每一次都不会发生。 我应该如何处理会话并使用新的PHP SDK访问令牌?

任何帮助将高度赞赏!

编辑

我发现在iFrame里面有一些IE / cookies / session的问题。 正如在这篇博文中看到 。 有了这个提示和一些进一步的研究,我在自举中添加了以下几行:

 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个用户的信息在login页面(authentication) – > formular – >和注册之间丢失了。 所以还有一些我错过了。

编辑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 。 如果是这种情况,我会将顶部位置redirect到Facebook页面和标签以获得新的签名请求 。 虽然这可能有助于解决这个问题,但我想阻止我的应用程序不得不redirect用户。

编辑3

经过几天密集的debugging和日志logging,我发现,来自FB.ui permissions.request方法$_REQUEST['session']很less是空的。

以下是我如何处理它:

这是我总是包括的东西:

 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; } 

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

Naitik类的作者删除了getSession()函数,现在如果你想知道用户是否被authentication,使用getUser()

对于Access令牌,非常简单,使用此函数getAccessToken() ,您将获得访问令牌以进行Graph或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); 

我的解决scheme

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

如果发生这种情况,出了问题。 但是这个小东西让我疯狂。 由于这种情况发生的频率很低,我可以忍受重新导向的用户回到facebook标签来获得一个新的签名请求。 有了新的JS SDK,希望这不会再发生。

更新:最终解决scheme

有一件事我监督,解决办法可以在这里find: FB是没有定义的问题
我没有asynchronous加载JS SDK ! 这解释了一切。 有时候all.js文件加载速度不够快,所以出现了JS错误。 因此,权限对话框和JSvalidation都不起作用,并且发送了空的#sessioninput值。

对于初学者,我会debugging一点。 logging请求的内容。 存储在$ _SESSION中的是$ _REQUEST中传递的内容。 此外,检查是否是浏览器问题(是否发生,无论浏览器,还是有一种模式?)

但是由于修复了IE(P3P头文件)中的cookie问题,我的猜测是还有一些浏览器被拒绝,否认第三方的cookies。 据我所知,一些版本的Safari和Opera默认是这样做的。 另外,这个错误指出没有提供access_token ,而不是无效的或过期的。

您可以通过禁用第三方cookie(例如在firefox中使用about:config ),取消授权您的应用程序(使用Facebook隐私设置底部的“应用程序和网站”部分),删除Cookie(与您的canvasURL相关)然后启动应用程序。

顺便说一句,即使在应用程序中,也总是有可能不会返回访问令牌,如错误17236所述

嗨,我已经运行在同样的麻烦,似乎我已经解决了与JS API和redirect到PHP的SDKlogin页面,如果用户信息可读

例:

 <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> 

如果脚本成功加载login页面,用户就被JS和PHP SDK认可了;)

仅供参考,Facebook在2小时前发布了PHP SDK的更新,如果您使用JavaScript SDK在客户端上创build会话,则会添加对新Cookie格式的支持。 更新可以在Facebook PHP-SDK GitHub仓库中find 。