6

真的很奇怪,使用 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 开发人员中,我定义了应用程序域 (domain.com) 和站点 URL ( http://domain.com/ )。已经尝试了带/不带斜杠的站点 URL,但没有解决问题。

知道发生了什么,为什么 Facebook PHP SDK 没有立即检测到用户的会话/不断丢失用户的会话并需要重新加载?这个问题确实会导致糟糕的用户体验。

非常感谢!

罗宾

4

2 回答 2

5

我最近遇到了同样的问题,似乎如果在 5 分钟左右不活动后重新加载,会话不会持续。有时有效,有时无效。

上周我一直在研究它,我能想到的唯一解决方案是使用 JS SDK 进行页面重新加载:

FB.Event.subscribe('auth.login', function(response) {
      window.location.reload();
    });

但我同意,就用户体验而言,这不是一个非常优雅的解决方案。您应该传递 cookiePHP SDK 中的参数和 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();

如果返回 0 对你没有好处$user。但是,在进行了一些挖掘之后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);

是我也做过的事情,它有所作为。:)

于 2013-01-06T20:42:44.433 回答
0

可能是因为 Facebook PHP SDK 不是 ajax,而且我们使用的是 PHP 页面,而且我们的服务器加载速度比 Facebook 的身份验证过程更快,以读取有效会话。Facebook PHP SDK 需要的是从我们的应用程序中刷新会话验证页面的东西,这应该内置到 Facebook Javascript SDK 中,但看起来它不是。

于 2013-10-04T13:41:01.380 回答