如何使用 Facebook PHP SDK 3.0 正确处理会话和访问令牌?
在 PHP 3.0 SDK 中,没有 getSession()
或任何来自 Facebook api 之外的会话处理可用.根据这篇博文 和 此错误报告.
In the PHP 3.0 SDK there is no getSession()
or any session handling from outside the Facebook api available. Some days ago the developers of facebook have also somehow updated the JavaScript sdk, according to this blog entry and this bug report.
在过去几天内,发生了变化引入托管的 JS SDK这打破了它之间的所有兼容性和当前的 PHP SDK(2.x 和 3.x).同时使用 JS 和他们网站上的 PHP SDK 很可能查看服务器端 API 故障.
Within the last few days, a change was introduced into the hosted JS SDK which broke all compatility between it and the current PHP SDK (2.x and 3.x). Developers who utilize both the JS and PHP SDK on their websites are likely to see server-side API failure.
但是,我不知道这是否真的影响了我的问题.就像在这个问题的答案我正在使用 PHP 检索 OAuth 对话框的访问令牌并将新的访问令牌保存在会话中.
However, I don't know if that really effects my problem. Like in this question's answer I am retrieving the access token of the OAuth dialog with PHP and save the new access token in the session.
以下代码显示了我如何处理此会话.$_REQUEST['session']
是 OAuth 对话框的响应内容.
The following code shows how I am handling this sessions. $_REQUEST['session']
is the content of the response of the OAuth dialog.
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'] = '';
}
以下是我处理用户数据的方式:
Here is how I handle the user data:
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);
}
}
测试时一切正常.仅发生一次错误:第一次在设置权限后.现在,由于该应用程序在线,似乎平均每第二个用户都会发生错误
Everything looks fine while testing. Only once an error occured: the first time after permission was set. Now, since the app is online, it seems as if the error occurs on average with every second user in
$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 正确处理会话和访问令牌?
So why is this happening? It is very hard to debug since the error seems to only occur when a user enters the app the first time, after the app authentication and the access token has changed. And even that is not happening every time. How should I handle the session and access token right with the new PHP SDK?
任何帮助将不胜感激!
我发现 iFrame 中的 cookie/会话存在一些 IE 问题.正如在这篇博文中所见.有了这个提示和一些进一步的研究,我在引导程序中添加了以下几行:
I found out that there are some IE issues with cookies/session inside an iFrame. As seen in this blog post. With that hint and some further research I added the following lines in my bootstrap:
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 个的信息在登陆页面(身份验证)-> 公式-> 和注册之间丢失了.所以我还是错过了一些东西.
Now its much better, but the information from about 2 of 50 users get lost between the steps landing page (authentication) -> formular -> and registration. So there is still something I missed.
我编辑了我的用户处理
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
}
这似乎有点帮助.我认为主要问题出在我的会话中.
This seems to help a little bit. I think the main problem is somewhere in my session.
此外,我添加了一个 try/catch 块,以查看是否在我的应用程序中的某个地方抛出了 Facebook OAuthException
.如果是这种情况,我会将顶部位置重定向到 Facebook 页面和标签以获取新签名请求.虽然这可能有助于解决这个问题,但我想防止我的应用程序不得不重定向用户.
Furthermore I added a try/catch block to see if somewhere in my app a Facebook OAuthException
is thrown. If this is the case, I redirect the top location to the Facebook Page and Tab to get a new signed request. Though this might help solve this problem, I want to prevent my app from having to redirect the user.
经过几天的密集调试和日志记录后,我发现来自 FB.ui permissions.request 方法 的 $_REQUEST['session']
是空的很少.
After some days of intense debugging and logging I found out, that the $_REQUEST['session']
coming from the FB.ui permissions.request method is empty infrequently.
我是这样处理的:
这是我一直包含的内容:
This is the stuff I always included:
FB.provide("UIServer.Methods", {'permissions.request': {size : {width: 575, height: 300}, url: 'connect/uiserver.php', transform : FB.UIServer.genericTransform}});
这个函数在表单提交时被调用.一直为我工作,但不知何故它仍然发送表单,尽管 session == ''
.
And this function is called on form submit. Always worked for me, but somehow it still sends the form although 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;
}
我的解决方案
好吧,由于在新的 JS SDK 出现之前我所做的一切都只是一种解决方法,因此似乎没有最佳实践.将 session.use_trans_sid
设置为 1 并添加 P3P 标头有助于克服 IE iFrame cookie 问题(请参阅我的第一个编辑).经过几天的大量调试,我发现 FB.ui 的 permission_request
不会每次都发送新的访问令牌(
My solution
Well, since everything I did was just a workaround until the new JS SDK comes out, there seems to be no best practice. Setting session.use_trans_sid
to 1 and adding the P3P header helped to overcome IE iFrame cookie issues (see my first edit). After a few days of heavy debugging I found out, that FB.ui's permission_request
does not send a new access token everytime (<5%).
如果发生这种情况,说明出了点问题.但这点小事让我发疯.由于这种情况很少发生,我可以忍受将用户重定向回 facebook 选项卡以获取新的签名请求.使用新的 JS SDK,希望不会再发生这种情况.
If this happens, something went wrong. But this little something is driving me crazy. Since this happens infrequently, I can bear redirecting users back to the facebook tab to get a new signed request. With the new JS SDK, hopefully, this won't happen anymore.
我监督了一件小事,可以在这里找到解决方案:FB 未定义问题
我没有异步加载JS SDK!这说明了一切.有时候all.js文件加载不够快,所以出现了JS错误.因此,权限对话框和 JS 验证都不起作用,并且发送了一个空的 #session 输入值.
There was one little thing I have overseen and the solution can be found here: FB is not defined problem
I did not load the JS SDK asynchronously! This explains everything. Sometimes the all.js file was not loaded fast enough, so there was a JS error. Due to that, neither the permission dialog nor the JS validation worked and an empty #session input value was sent.