Javascript 如何使用 Facebook PHP SDK 3.0 正确处理会话和访问令牌?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6468103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly handle session and access token with Facebook PHP SDK 3.0?
提问by Sascha Galley
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 entryand this bug report.
在 PHP 3.0 SDK 中,没有getSession()
或任何来自 Facebook api 外部的会话处理可用。根据此博客条目和此错误报告,几天前 facebook 的开发人员也以某种方式更新了 JavaScript sdk 。
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.
在最近几天内,托管 JS SDK 中引入了一项更改,这破坏了它与当前 PHP SDK(2.x 和 3.x)之间的所有兼容性。在其网站上同时使用 JS 和 PHP SDK 的开发人员很可能会看到服务器端 API 失败。
However, I don't know if that really effects my problem. Like in this question's answerI am retrieving the access token of the OAuth dialog with PHP and save the new access token in the session.
但是,我不知道这是否真的影响了我的问题。就像在这个问题的答案中一样,我正在使用 PHP 检索 OAuth 对话框的访问令牌,并将新的访问令牌保存在会话中。
Current workaround
当前的解决方法
The following code shows how I am handling this sessions. $_REQUEST['session']
is the content of the response of the OAuth dialog.
以下代码显示了我如何处理此会话。$_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'] = '';
}
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);
}
}
The Problem
问题
Everything looks fine while testing. Only once an error occured: the first timeafter 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');
with the error:
有错误:
An active access token must be used to query information about the current user.
Question
题
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?
那么为什么会发生这种情况呢?调试非常困难,因为错误似乎只发生在用户第一次进入应用程序时,在应用程序身份验证和访问令牌更改后。甚至这也不是每次都发生。我应该如何使用新的 PHP SDK 正确处理会话和访问令牌?
Any help would be highly appreciatied!
任何帮助将不胜感激!
Edit
编辑
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:
我发现 iFrame 中的 cookie/会话存在一些 IE 问题。正如这篇博文中所见。有了这个提示和一些进一步的研究,我在引导程序中添加了以下几行:
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"');
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.
现在好多了,但是大约 50 个用户中有 2 个的信息在登陆页面(身份验证)-> 公式-> 和注册之间丢失了。所以我仍然错过了一些东西。
Edit 2
编辑 2
I edited my user handling from
我编辑了我的用户处理
if ($this->user === false || is_null($this->user)) {
// get user data
}
to
到
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.
这似乎有点帮助。我认为主要问题出在我的会话中。
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 locationto 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.
此外,我添加了一个 try/catch 块来查看我的应用程序中是否有 FacebookOAuthException
被抛出。如果是这种情况,我会将顶部位置重定向到 Facebook Page 和 Tab 以获取新的签名请求。虽然这可能有助于解决这个问题,但我想防止我的应用程序不得不重定向用户。
Edit 3
编辑 3
After some days of intense debugging and logging I found out, that the $_REQUEST['session']
coming from the FB.ui permissions.request methodis empty infrequently.
经过几天的密集调试和日志记录,我发现$_REQUEST['session']
来自FB.ui permissions.request 方法的消息很少为空。
Here is how I handle it:
这是我如何处理它:
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}});
And this function is called on form submit. Always worked for me, but somehow it still sends the form although session == ''
.
这个函数在表单提交时调用。一直为我工作,但不知何故它仍然发送表单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;
}
采纳答案by Sascha Galley
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%).
好吧,由于在新的 JS SDK 出现之前我所做的一切都只是一种解决方法,因此似乎没有最佳实践。设置session.use_trans_sid
为 1 并添加 P3P 标头有助于克服 IE iFrame cookie 问题(请参阅我的第一个编辑)。经过几天的大量调试,我发现 FB.uipermission_request
不会每次都发送新的访问令牌(<5%)。
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.
如果发生这种情况,说明出了点问题。但是这个小东西让我发疯。由于这种情况很少发生,我可以忍受将用户重定向回 facebook 选项卡以获取新的签名请求。使用新的 JS SDK,希望不会再发生这种情况。
Update: final solution
更新:最终解决方案
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.
我监督了一件小事,可以在此处找到解决方案:FB 未定义问题
我没有异步加载 JS SDK!这说明了一切。有时候all.js文件加载不够快,所以出现了JS错误。因此,权限对话框和 JS 验证都不起作用,并且发送了一个空的 #session 输入值。
回答by Hamza
I'm using now PHP SDK 3.xwithout any problem.
我现在使用PHP SDK 3.x没有任何问题。
Naitik the class author removed the getSession()function, and now if you want to know if the user is authenticated or not, use getUser().
Naitik 类作者删除了getSession()函数,现在如果您想知道用户是否通过身份验证,请使用getUser()。
For Access token, it's very simple, use this function getAccessToken(), and you'll get the access token to make Graph or Rest APIcalls.
对于访问令牌,非常简单,使用该函数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);
回答by Maciej ?ebkowski
For starters, I would debug a little more. Log the contents of the requests. What's stored in $_SESSION, what's passed in $_REQUEST. Also, check if it's a browser issue (is it happening regardless of the browser, or is there a pattern?)
对于初学者,我会多调试一点。记录请求的内容。$_SESSION 中存储的内容,$_REQUEST 中传递的内容。另外,检查它是否是浏览器问题(是否与浏览器无关,或者是否存在模式?)
But since fixing the cookie issue in IE (P3P header) helped, my guess is that there are some browsers left, that deny third party cookies. As far as I know, some versions of Safari and Opera does that by default.
In addition, this error states that there was no access_token
provided, as opposed to invalid or expired one.
但是由于修复 IE 中的 cookie 问题(P3P 标头)有所帮助,我的猜测是还有一些浏览器会拒绝第三方 cookie。据我所知,某些版本的 Safari 和 Opera 会默认这样做。此外,此错误指出没有access_token
提供,而不是无效或过期的。
You can test that by disabling third party cookies (using about:config in firefoxfor instance), deauthorizing your app (using the "Apps and websites" section on the bottom of Facebook Privacy settings), deleting cookies (related to your canvas URL) and then launching the application.
您可以通过禁用第三方 cookie(例如在 firefox 中使用 about:config)、取消对您的应用的授权(使用Facebook 隐私设置底部的“应用和网站”部分)、删除 cookie(与您的画布 URL 相关)来进行测试然后启动应用程序。
BTW, there's always a possibility of facebook not returning access token even when it should, as described in bug 17236
顺便说一句,Facebook 总是有可能不返回访问令牌,即使它应该返回,如错误 17236 中所述
回答by benny
Hi i've run in the same trouble seems i've solved it with watching the JS API and redirect to the PHP-SDK Login Page if User Information is readable
嗨,我遇到了同样的麻烦,似乎我已经通过观看 JS API 解决了这个问题,如果用户信息可读,则重定向到 PHP-SDK 登录页面
example:
例子:
<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>
if the script succed it loads the loginpage, and user got recognized by both JS and PHP SDK ;)
如果脚本成功,它会加载登录页面,并且用户会被 JS 和 PHP SDK 识别;)
回答by Rob DiMarco
FYI, Facebook posted an update to the PHP SDK about 2 hours ago which adds support for the new cookie format, if you're creating a session on the client using the JavaScript SDK. The update can be found at the Facebook PHP-SDK GitHub repo.
仅供参考,如果您使用 JavaScript SDK 在客户端上创建会话,Facebook 大约 2 小时前发布了对 PHP SDK 的更新,增加了对新 cookie 格式的支持。可以在Facebook PHP-SDK GitHub 存储库中找到该更新。