简体   繁体   English

Facebook PHP SDK会话丢失,需要JS SDK刷新

[英]Facebook PHP SDK session lost, needs JS SDK refresh

Really strange, it seems like the Facebook session is lost ($user = 0) using the PHP SDK (v 3.2.2). 真的很奇怪,使用PHP SDK(v 3.2.2)似乎丢失了Facebook会话($ user = 0)。 The JS SDK needs to reload my page to recover the Facebook session. JS SDK需要重新加载我的页面以恢复Facebook会话。 This problem occurs now and then, sometimes the Facebook session is lost, sometimes it works just fine. 这个问题偶尔会发生,有时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;
  } 
}

The main problem is that $user = $facebook->getUser(); 主要问题是$ user = $ facebook-> getUser(); returns 0. However, as the user is actually connected, the JS SDK detects the auth.login event and reloads the page (another strange thing, I use auth.login because the auth.authResponseChange event keeps getting fired every second). 但是,当用户实际连接时,JS SDK会检测auth.login事件并重新加载页面(另一个奇怪的事情是,我使用auth.login,因为auth.authResponseChange事件每秒都会被触发)。 Now $user = $facebook->getUser(); 现在$ user = $ facebook-> getUser(); returns the user's uid. 返回用户的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();
  });
};

In Facebook Developer I defined the App Domain (domain.com) and Site Url ( http://domain.com/ ). 在Facebook Developer中,我定义了App Domain(domain.com)和Site Url( http://domain.com/ )。 Already tried Site Url with/without trailing slash, didn't solve the problem. 已经尝试使用/不带斜杠的Site Url,没有解决问题。

Any idea what's going on, why the Facebook PHP SDK doesn't detect the user's session immediately / keeps losing the user's session and needs a reload? 知道发生了什么,为什么Facebook PHP SDK没有立即检测到用户的会话/不断丢失用户的会话并需要重新加载? This problem really causes a bad UX. 这个问题确实导致用户体验不好。

Thanks a lot! 非常感谢!

Robin 知更鸟

I've come accross the same problem lately, it seems that if after 5mins or so of inactivity you do a reload, the session does not persist. 我最近遇到了同样的问题,似乎如果你在5分钟左右的时间没有进行重新加载,那么会话就不会持续存在。 Sometimes it works, sometimes it doesn't. 有时候它有效,有时则不然。

I've been looking into it for about the last week, and the only solution I could think of was to use the JS SDK to do a page reload with: 我在上周一直在研究它,我能想到的唯一解决方案是使用JS SDK进行页面重新加载:

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

But I agree, it's not a very elegant solution in terms of UX. 但我同意,就UX而言,这不是一个非常优雅的解决方案。 You should pass the cookie param in the PHP SDK, and the oauth param in JS SDK, and see if that works (it didn't for me): 您应该在PHP SDK中传递cookie参数,在JS SDK中传递oauth参数,看看它是否有效(它不适合我):

$facebook = new Facebook(array(
  'appId'  => $config['facebook']['id'],
  'secret' => $config['facebook']['secret'],
  'cookie' => true
));

AND

FB.init({
    appId : appId,
    channelUrl : '//domain.com/signon/channel.php',
    status     : true,
    cookie     : true,
    xfbml      : true,
    oauth      : true
  }); 

Stranger even still, I re-downloaded the latest PHP SDK from Github and uploaded it to a sandbox environment (Apache, PHP 5.4). 甚至更奇怪的是,我从Github重新下载了最新的PHP SDK并将其上传到沙箱环境(Apache,PHP 5.4)。 I ran the example (with the JS SDK) AS-IS and it has the same issue! 我运行示例(使用JS SDK)AS-IS,它有同样的问题!

Now if the above just doesn't cut the mustard, I have some more suggestions. 现在,如果以上只是没有削减芥末,我还有一些建议。

CHANGING THE SDK UP A BIT 改变SDK的位置

Firstly, passing 首先,通过

$facebook->getAccessToken();

will do you no good if $user returns 0. However, after doing a bit of digging around in base_facebook.php , I noticed that the method getCode() actually uses $_REQUEST to retrieve the authorization code from the query parameters. 如果$user返回0,那对你没有$user但是,在对base_facebook.php进行了一些挖掘base_facebook.php ,我注意到方法getCode()实际上使用$_REQUEST从查询参数中检索授权代码。

from the PHP Manual, $_REQUEST is 从PHP手册,$ _REQUEST是

An associative array that by default contains the contents of $_GET, $_POST and $_COOKIE. 一个关联数组,默认情况下包含$ _GET,$ _POST和$ _COOKIE的内容。

BUT

It is very different to $_GET,$_POST or $_COOKIE. 它与$ _GET,$ _ POST或$ _COOKIE非常不同。

This can be a bit of a bugger depending on your setup. 根据您的设置,这可能是一个bugger。 So instead, find the function getCode() in base_facebook.php that looks like this: 所以相反,在base_facebook.php中找到如下所示的函数base_facebook.php getCode()

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;
}

and merge the query into a new array/variable (let's call it $code_array ) to include the $_GET , $_POST & $_COOKIE arrays using array_merge() like so: 并将查询合并到一个新的数组/变量(让我们称之为$code_array ),使用array_merge()包含$_GET$_POST$_COOKIE数组,如下所示:

$code_array = array_merge($_GET,$_POST,$_COOKIE);

What you end up with is an array that contains all the data from the respective requests. 您最终得到的是一个包含来自相应请求的所有数据的数组。 The just go ahead and replace $_REQUEST with $code_array inside the function, ie 只需继续使用函数内的$code_array替换$_REQUEST ,即

\\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

This should do the job nicely (hopefully). 这应该很好地完成工作(希望如此)。

OPTIONAL - Extending your Access Token Lifetime 可选 - 延长您的访问令牌生命周期

This is optional, but I included it anyway. 这是可选的,但无论如何我都包含了它。 Most New Apps will already have long lived Access Tokens, but just in case, you can use the $facebook->setExtendedAccessToken(); 大多数新应用程序已经拥有长期访问令牌,但为了以防万一,您可以使用$facebook->setExtendedAccessToken(); method to transform your existing access token. 转换现有访问令牌的方法。

Note: You have to call $facebook->setExtendedAccessToken(); 注意:您必须调用$facebook->setExtendedAccessToken(); before you actually get your access token with the getAccessToken() method. 在使用getAccessToken()方法实际获取访问令牌之前。

Now, using your code you will have 现在,使用您的代码

$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..

CONCLUSION 结论

Breaking $_REQUEST into $_GET,$_POST & $_COOKIE (Even though it includes all three by default) seems to ensure we can fetch the cookie that was set by the SDK(s) without much trouble. 将$ _REQUEST分解为$ _GET,$ _ POST和$ _COOKIE(即使它默认包含所有三个)似乎确保我们可以毫不费力地获取SDK设置的cookie。 I say seems because heck, I'm not really 100% sure myself. 我说似乎是因为哎呀,我真的不是很自信。

I Used the above methods to get it working in my case, so I'm hoping to share some knowledge, as I've been losing far too much sleep over this problem, and couldn't find a viable solution. 我使用上面的方法让它在我的情况下工作,所以我希望分享一些知识,因为我已经在这个问题上失去了太多的睡眠,并且找不到可行的解决方案。

Hope this helps! 希望这可以帮助!

EDIT: I forgot to mention, changing the API request from 编辑:我忘记提及,更改API请求

$user_profile = $facebook->api('/me');

to

$user_profile = $facebook->api('/'.$user.'?access_token='.$access_token);

was something I also did, and it made a difference. 这也是我也做过的事情,它起了作用。 :) :)

Maybe because the Facebook PHP SDK is not ajax and we are using PHP pages and our servers load faster than the authentication process from Facebook to read back a valid session. 也许是因为Facebook PHP SDK不是ajax而且我们使用的是PHP页面,而且我们的服务器加载速度比Facebook的认证过程更快,以回读有效的会话。 what the Facebook PHP SDK requires is something to refresh the page on session validation from our apps, this should be built in to the Facebook Javascript SDK but it looks like it isn't. Facebook PHP SDK需要的是从我们的应用程序刷新会话验证的页面,这应该内置到Facebook Javascript SDK,但它看起来不是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM