2013-01-05 112 views
6

真的很奇怪,它似乎使用PHP SDK(v 3.2.2)丟失了Facebook會話($ user = 0)。 JS SDK需要重新加載我的頁面來恢復Facebook會話。此問題現在出現,然後,有時Facebook會話丟失,有時它工作得很好。Facebook PHP SDK會話丟失,需要JS SDK刷新

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)和站點地址(http://domain.com/)。已嘗試使用/不使用結尾斜槓的Site Url,並未解決問題。

任何想法是怎麼回事,Facebook PHP SDK爲什麼不立即檢測用戶的會話/不斷丟失用戶的會話,需要重新加載?這個問題真的會導致糟糕的用戶體驗

非常感謝!

羅賓

回答

5

我來翻過了同樣的問題最近,它看來,如果5分鐘後左右活動的你做了重裝,會話不會保留。有時它起作用,有時它不起作用。

我一直在尋找到它大約在上週,我能想到的唯一的解決辦法是使用JS SDK做一個頁面重新加載與:

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

但我同意,這是用戶體驗方面不是一個非常優雅的解決方案。你應該通過在PHP SDK的cookie PARAM,並在JS SDK中的OAuth PARAM,並看看是否能工程(它沒有對我來說):

$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下載了latest 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。

這可能是一個取決於您的設置的一個bug。因此,相反,找到函數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)包括使用array_merge()像這樣的$_GET$_POST & $_COOKIE陣列:

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

你最終得到的是一個數組,其中包含來自各個請求的所有數據。該先走一步,與$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 

這應該做的工作很好(希望)。

可選 - 擴展您的訪問令牌生存

這是可選的,但我把它反正。大多數新應用程序都將擁有長期存在的訪問令牌,但以防萬一,您可以使用$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%確定我自己。

我用上面的方法讓它在我的情況下工作,所以我希望分享一些知識,因爲我一直在這個問題上失去了太多的睡眠,並且找不到可行的解決方案。

希望這會有所幫助!

編輯:我忘了提,從

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

改變API請求

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

事情我也做過,這使不同。 :)

+0

調用'$ facebook-> setExtendedAccessToken();'爲我工作,謝謝。 – Eldar

+0

我有一個應用程序的網站在根和iframe小部件/小部件。 除了你在基地Facebook的變化,我還必須爲/ widgets中的iframe小部件創建一個新的應用程序。現在根域的會話似乎沒問題。 –

+0

我回過頭來看,會話很好,但用戶在頁面閒置幾分鐘後仍然返回0。 –

0

也許是因爲Facebook的PHP SDK不是ajax,我們正在使用PHP頁面,我們的服務器加載速度比從Facebook認證過程讀取有效的會話。 Facebook PHP SDK需要什麼來刷新我們應用程序的會話驗證頁面,這應該內置到Facebook Javascript SDK中,但看起來不是這樣。