6

Really strange, it seems like the Facebook session is lost ($user = 0) using the PHP SDK (v 3.2.2). The JS SDK needs to reload my page to recover the Facebook session. This problem occurs now and then, sometimes the Facebook session is lost, sometimes it works just fine.

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(); 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). Now $user = $facebook->getUser(); returns the user's 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/). Already tried Site Url with/without trailing slash, didn't solve the problem.

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? This problem really causes a bad UX.

Thanks a lot!

Robin

4

2 に答える 2

5

私は最近同じ問題に遭遇しました.5分ほど非アクティブの後にリロードを行うと、セッションが持続しないようです. うまくいくこともあれば、うまくいかないこともあります。

先週くらい調べてみたのですが、考えられる唯一の解決策は、JS SDK を使用してページをリロードすることでした。

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

しかし、UX の点ではあまりエレガントなソリューションではないことに同意します。PHP SDK でパラメーターを渡し、 cookieJS 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 を使用して) AS-IS で実行しましたが、同じ問題が発生しました。

上記がマスタードをカットしない場合は、さらにいくつかの提案があります.

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 に分割すると (デフォルトで 3 つすべてが含まれますが)、SDK によって設定された Cookie を問題なく取得できるようです。私が言っているのは、私自身が 100% 確信を持っているわけではないからです。

上記の方法を使用して私の場合に機能させたので、この問題であまりにも多くの睡眠を失っており、実行可能な解決策を見つけることができなかったため、いくつかの知識を共有したいと考えています.

お役に立てれば!

編集:言及するのを忘れて、APIリクエストをから変更しました

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

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

私もやったことがあり、違いがありました。:)

于 2013-01-06T20:42:44.433 に答える