在PHP 3.0 SDK中,没有 getSession()
或来自Facebook api外部的任何会话处理 . 根据 this blog entry 和 this 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 回答
嗨,我遇到了同样的麻烦似乎我已经解决了它看着JS API并重定向到PHP-SDK登录页面,如果用户信息是可读的
例:
如果脚本成功加载了登录页面,并且用户已被JS和PHP SDK识别;)
对于初学者,我会调试一下 . 记录请求的内容 . 什么存储在$ _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
我的解决方案
好吧,因为我所做的一切只是一个解决方法,直到新的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输入值 .
仅供参考,Facebook大约2小时前发布了PHP SDK的更新,如果您使用JavaScript SDK在客户端上创建会话,则会增加对新cookie格式的支持 . 更新可以在Facebook PHP-SDK GitHub repo找到 .
我现在正在使用 PHP SDK 3.x 没有任何问题 .
类作者Naitik删除了 getSession() 函数,现在如果您想知道用户是否经过身份验证,请使用 getUser() .
对于Access令牌,它非常简单,使用此函数 getAccessToken() ,您将获得访问令牌以进行 Graph or Rest API 调用 .