真的很奇怪,使用 PHP SDK (v 3.2.2) 似乎 Facebook 会话丢失了 ($user = 0)。 JS SDK 需要重新加载我的页面以恢复 Facebook 会话。这个问题时有发生,有时 Facebook 会话丢失,有时它工作正常。
session_start();
// Run Facebook API
$facebook = new Facebook(array(
'appId' => $config['facebook']['id'],
'secret' => $config['facebook']['secret']
));
// Fetch user
$user = $facebook->getUser();
if($user) {
try {
// Just to be sure, add access token to each request
$user['access_token'] = $facebook->getAccessToken();
// Fetch user details
$user = $facebook->api('/me?access_token='.$user['access_token']);
}
catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
主要问题是 $user = $facebook->getUser();返回 0。但是,当用户实际连接时,JS SDK 检测到 auth.login 事件并重新加载页面(另一件奇怪的事情,我使用 auth.login 因为 auth.authResponseChange 事件每秒都会被触发)。现在 $user = $facebook->getUser();返回用户的 uid.
window.fbAsyncInit = function() {
FB.init({
appId : appId,
channelUrl : '//domain.com/signon/channel.php',
status : true,
cookie : true,
xfbml : true
});
FB.Event.subscribe('auth.login', function(response) {
location.reload();
});
};
在 Facebook Developer 中,我定义了 App Domain (domain.com) 和 Site Url (http://domain.com/)。已经尝试过带/不带尾部斜杠的站点 Url,但没有解决问题。
知道发生了什么,为什么 Facebook PHP SDK 没有立即检测到用户会话/不断丢失用户会话并需要重新加载?这个问题确实会导致糟糕的用户体验。
非常感谢!
罗宾
我最近遇到了同样的问题,似乎如果在 5 分钟左右不活动后重新加载,会话不会持续。有时有效,有时无效。
上周我一直在研究它,我能想到的唯一解决方案是使用 JS SDK 重新加载页面:
FB.Event.subscribe('auth.login', function(response) {
window.location.reload();
});
但我同意,就用户体验而言,这不是一个非常优雅的解决方案。您应该在 PHP SDK 中传递
cookie
参数,在 JS SDK 中传递 oauth 参数,看看是否有效(对我来说无效):
$facebook = new Facebook(array(
'appId' => $config['facebook']['id'],
'secret' => $config['facebook']['secret'],
'cookie' => true
));
和
FB.init({
appId : appId,
channelUrl : '//domain.com/signon/channel.php',
status : true,
cookie : true,
xfbml : true,
oauth : true
});
陌生人,我从 Github 重新下载了最新的 PHP SDK,并将其上传到沙箱环境(Apache,PHP 5.4)。我按原样运行示例(使用 JS SDK),它有同样的问题!
现在,如果以上内容还不能解决问题,我还有一些建议。
稍微改变一下 SDK
首先,通过
$facebook->getAccessToken();
如果 $user
返回 0,对您没有好处。但是,在
base_facebook.php
中进行了一些挖掘之后,我注意到方法 getCode()
实际上使用 $_REQUEST
从查询参数中检索授权代码。
来自 PHP 手册,$_REQUEST 是
一个关联数组,默认包含 $_GET、$_POST 和 $_COOKIE 的内容。
但是
它与$_GET、$_POST 或$_COOKIE 有很大不同。
根据您的设置,这可能有点麻烦。因此,相反,在
getCode()
中找到函数base_facebook.php
,如下所示:
protected function getCode() {
if (isset($_REQUEST['code'])) {
if ($this->state !== null &&
isset($_REQUEST['state']) &&
$this->state === $_REQUEST['state']) {
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
return $_REQUEST['code'];
} else {
self::errorLog('CSRF state token does not match one provided.');
return false;
}
}
return false;
}
并将查询合并到一个新的数组/变量(我们称之为
$code_array
)以包含$_GET
,$_POST
和$_COOKIE
数组使用array_merge()
像这样:
$code_array = array_merge($_GET,$_POST,$_COOKIE);
你最终得到的是一个包含来自各个请求的所有数据的数组。只需继续并在函数内用
$_REQUEST
替换$code_array
,即
\\replace $_REQUEST with $code_array;
if (isset($code_array['code'])) {
if ($this->state !== null &&
isset($code_array['state']) &&
$this->state === $code_array['state']) { //...and so on for the rest
这应该能很好地完成工作(希望如此)。
可选 - 延长您的访问令牌生命周期
这是可选的,但我还是包含了它。大多数新应用程序已经拥有长期存在的访问令牌,但为了以防万一,您可以使用
$facebook->setExtendedAccessToken();
方法来转换现有的访问令牌。
注意: 在使用
$facebook->setExtendedAccessToken();
方法实际获取访问令牌之前,您必须先调用 getAccessToken()
。
现在,使用您的代码您将拥有
$user = $facebook->getUser();
if($user) {
try {
// Just to be sure, add access token to each request
$facebook->setExtendedAccessToken();
$access_token = $facebook->getAccessToken();
// Fetch user details
$user = $facebook->api('/me?access_token='.$access_token);
}
//and so on..
结论
将 $_REQUEST 分解为 $_GET、$_POST 和 $_COOKIE(尽管它默认包含所有这三个)似乎确保我们可以毫不费力地获取由 SDK 设置的 cookie。我说似乎是因为见鬼,我自己并不是真的 100% 确定。
我用上面的方法让它在我的案例中工作,所以我希望分享一些知识,因为我已经为这个问题失去了太多的睡眠,并且找不到可行的解决方案。
希望这有帮助!
编辑: 我忘了说,改变 API 请求从
$user_profile = $facebook->api('/me');
到
$user_profile = $facebook->api('/'.$user.'?access_token='.$access_token);
是我也做过的事情,它有所作为。 :)
可能是因为 Facebook PHP SDK 不是 ajax,我们使用 PHP 页面,我们的服务器加载速度比 Facebook 的身份验证过程更快,可以读取有效会话。 Facebook PHP SDK 需要的是从我们的应用程序刷新会话验证页面,这应该内置在 Facebook Javascript SDK 中,但看起来它不是。