如何使用 Facebook PHP SDK 3.0 正确处理会话和访问令牌?
Posted
技术标签:
【中文标题】如何使用 Facebook PHP SDK 3.0 正确处理会话和访问令牌?【英文标题】:How to properly handle session and access token with Facebook PHP SDK 3.0? 【发布时间】:2011-09-22 00:35:33 【问题描述】:在 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);
问题
测试时一切正常。仅发生一次错误:第一次设置权限后。现在,由于该应用程序处于在线状态,似乎平均每第二个用户就会发生错误
$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 中的 cookie/会话存在一些 IE 问题。正如所见 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
。如果是这种情况,我会将 顶部位置 重定向到 Facebook 页面和选项卡以获取 新签名请求。虽然这可能有助于解决这个问题,但我想防止我的应用程序不得不重定向用户。
编辑 3
经过几天的紧张调试和日志记录,我发现来自 FB.ui permissions.request 方法的$_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;
【问题讨论】:
您能否提供更多关于您的“引导程序”是什么以及它还包含什么的信息? @danjp 我的引导程序包含路径配置、自动加载器、配置和会话处理。与我的问题唯一相关的是我已经发布的内容:use_trans_sid
和 P3P 标头。
+1 用于提及 p3p 标头。当我试图在 ASP.NET 中创建 Facebook 应用程序时,这些事情让我死了好几个星期。
【参考方案1】:
我现在使用 PHP SDK 3.x 没有任何问题。
类作者 Naitik 删除了 getSession() 函数,现在如果您想知道用户是否经过身份验证,请使用 getUser()。 p>
对于Access Token,很简单,使用getAccessToken()这个函数,就可以得到access token,进行Graph or Rest API调用。 p>
$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);
【讨论】:
你没有理解我的问题:我必须通过 JavaScript 获得许可。 PHP 3.x SKD 不能与当前可用的 JS SDK 很好地通信。访问令牌不会自动更改。因此,我编写了这个解决方法来将新的访问令牌保存在会话中。这只在大约 95% 的时间里有效......不是 100% @Sascha Galley - 你真的只需要使用 JS 获得许可吗?使用 PHP SDK 获取权限应该可以避免这个问题。 @Sergey Nester:我知道,但是这个项目和其他项目需要使用 JS 对话框。如果根本不可能将旧的 JS 与新的 PHP SDK 结合起来,我可以反对。但正如已经提到的,我的解决方法是>95%。只有一件小事让我无法做到 100%。我也可以捕获错误,重新加载整个页面并获取新的签名请求,但我想知道为什么会这样。【参考方案2】:对于初学者,我会调试更多。记录请求的内容。存储在 $_SESSION 中的内容,在 $_REQUEST 中传递的内容。另外,检查它是否是浏览器问题(无论浏览器如何都会发生,还是有规律?)
但由于修复 IE(P3P 标头)中的 cookie 问题有所帮助,我猜是还有一些浏览器会拒绝第三方 cookie。据我所知,某些版本的 Safari 和 Opera 默认会这样做。
此外,此错误表明没有提供access_token
,而不是提供无效或过期的。
您可以通过禁用第三方 cookie(例如 using about:config in firefox)、取消对您的应用的授权(使用 Facebook Privacy settings 底部的“应用和网站”部分)、删除 cookie(与您的画布 URL 相关)来测试这一点然后启动应用程序。
顺便说一句,Facebook 总是有可能不返回访问令牌,即使它应该返回,如 described in bug 17236
【讨论】:
谢谢,这是迄今为止最好的答案。我不会立即接受它,让它开放供进一步研究,但我现在给你应得的赏金。所以...敬请期待:)【参考方案3】:我的解决方案
好吧,由于在新的 JS SDK 出现之前我所做的一切都只是一种解决方法,因此似乎没有最佳实践。将session.use_trans_sid
设置为 1 并添加 P3P 标头有助于克服 IE iFrame cookie 问题(请参阅我的第一次编辑)。经过几天的大量调试,我发现 FB.ui 的permission_request
并不是每次都发送新的访问令牌(
如果发生这种情况,那就是出了问题。但是这个小东西让我发疯了。由于这种情况很少发生,我可以忍受将用户重定向回 facebook 选项卡以获取新的签名请求。希望有了新的 JS SDK,这种情况不会再发生了。
更新:最终解决方案
我监督了一件小事,可以在这里找到解决方案:FB is not defined problem 我没有异步加载 JS SDK!这解释了一切。有时 all.js 文件加载速度不够快,所以出现了 JS 错误。因此,权限对话框和 JS 验证都不起作用,并且发送了一个空的 #session 输入值。
【讨论】:
很高兴你把它整理好了!希望 PHP-SDK 能尽快更新,以便您正确集成系统。【参考方案4】:仅供参考,如果您使用 JavaScript SDK 在客户端上创建会话,Facebook 大约 2 小时前发布了对 PHP SDK 的更新,其中增加了对新 cookie 格式的支持。更新可以在Facebook PHP-SDK GitHub repo找到。
【讨论】:
【参考方案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 识别;)
【讨论】:
以上是关于如何使用 Facebook PHP SDK 3.0 正确处理会话和访问令牌?的主要内容,如果未能解决你的问题,请参考以下文章
Android 如何在新的 sdk 3.0 中与 Facebook Open Graph 共享数据?
在 iOS Facebook SDK 3.0 上作为粉丝页面发布