2013-01-05 52 views
6

Thật lạ, có vẻ như phiên Facebook bị mất ($ user = 0) bằng cách sử dụng PHP SDK (phiên bản 3.2.2). JS SDK cần phải tải lại trang của tôi để khôi phục phiên Facebook. Vấn đề này xảy ra ngay bây giờ và sau đó, đôi khi phiên Facebook bị mất, đôi khi nó hoạt động tốt.Phiên làm việc PHP PHP SDK bị mất, cần làm mới 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; 
    } 
} 

Vấn đề chính là $ user = $ facebook-> getUser(); trả về 0. Tuy nhiên, khi người dùng thực sự được kết nối, JS SDK phát hiện sự kiện auth.login và tải lại trang (một điều lạ khác, tôi sử dụng auth.login vì sự kiện auth.authResponseChange tiếp tục bị đuổi mỗi giây). Bây giờ $ user = $ facebook-> getUser(); trả về uid của người dùng.

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

Trong nhà phát triển Facebook Tôi đã xác định Tên miền ứng dụng (domain.com) và Url trang web (http://domain.com/). Đã thử Url trang web có/không có dấu gạch chéo, không giải quyết được sự cố.

Bất kỳ ý tưởng gì đang xảy ra, tại sao Facebook PHP SDK không phát hiện phiên của người dùng ngay lập tức/tiếp tục mất phiên của người dùng và cần tải lại? Vấn đề này thực sự gây ra một UX xấu.

Cảm ơn rất nhiều!

Robin

Trả lời

5

Tôi đã đi qua cùng một vấn đề thời gian gần đây, có vẻ như rằng nếu sau 5 phút hoặc lâu hơn không hoạt động bạn làm một tải lại, phiên không tồn tại. Đôi khi nó hoạt động, đôi khi nó không.

Tôi đã nhìn vào nó trong khoảng tuần trước, và giải pháp duy nhất tôi có thể nghĩ đến là sử dụng SDK JS để làm một tải lại trang bằng:

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

Nhưng tôi đồng ý, đó là không phải là một giải pháp rất thanh lịch về mặt UX. Bạn nên vượt qua cookie param trong PHP SDK, và param oauth trong JS SDK, và xem nếu mà làm việc (nó không cho tôi):

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

Stranger thậm chí vẫn còn, tôi tải lại các latest PHP SDK từ Github và tải nó lên một môi trường sandbox (Apache, PHP 5.4). Tôi chạy ví dụ (với JS SDK) AS-IS và nó có cùng một vấn đề!

Bây giờ nếu phần trên chỉ không cắt mù tạt, tôi có một số đề xuất khác.

thay đổi SDK lên một chút

Thứ nhất, đi qua

$facebook->getAccessToken();

sẽ làm bạn không tốt nếu $user lợi nhuận 0. Tuy nhiên, sau khi làm một chút về đào xung quanh trong base_facebook.php, Tôi nhận thấy rằng phương pháp getCode() thực sự sử dụng $_REQUEST để truy xuất mã ủy quyền từ các tham số truy vấn.

từ Manual PHP, $ _REQUEST là

Một mảng kết hợp mà theo mặc định chứa các nội dung của $ _GET, $ _POST và $ _COOKIE.

NHƯNG

Nó rất khác đến $ _GET, $ _ POST hoặc $ _COOKIE.

Điều này có thể hơi khó khăn tùy thuộc vào thiết lập của bạn. Vì vậy, thay vào đó, tìm ra chức năng getCode() trong base_facebook.php trông như thế này:

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

và hợp nhất các truy vấn vào một mảng mới/biến (chúng ta hãy gọi nó $code_array) để bao gồm $_GET, $_POST & $_COOKIE mảng sử dụng array_merge() như vậy :

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

Điều bạn kết thúc là một mảng chứa tất cả dữ liệu từ các yêu cầu tương ứng. Các chỉ cần đi trước và thay thế $_REQUEST với $code_array bên trong hàm, tức là

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

này nên làm công việc độc đáo (hy vọng).

TÙY CHỌN - Mở rộng truy cập Mã Lifetime của bạn

này là tùy chọn, nhưng tôi bao gồm nó anyway. Hầu hết các ứng dụng mới sẽ có các thẻ truy cập tồn tại lâu dài, nhưng chỉ trong trường hợp, bạn có thể sử dụng phương thức $facebook->setExtendedAccessToken(); để chuyển đổi mã thông báo truy cập hiện tại của mình.

Lưu ý: Bạn phải gọi $facebook->setExtendedAccessToken(); trước khi bạn thực sự nhận mã thông báo truy cập của bạn với phương pháp getAccessToken().

Bây giờ, sử dụng mã của bạn, bạn sẽ có

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

KẾT LUẬN

Breaking $ _REQUEST vào $ _GET, $ _ POST & $ _COOKIE (Mặc dù nó bao gồm tất cả ba theo mặc định) có vẻ đảm bảo rằng chúng tôi có thể tìm nạp cookie được SDK (bộ) đặt mà không gặp nhiều rắc rối. Tôi nói có vẻ vì heck, tôi không thực sự chắc chắn 100% bản thân mình.

Tôi đã sử dụng các phương pháp trên để làm việc trong trường hợp của mình, vì vậy tôi hy vọng chia sẻ một số kiến ​​thức, vì tôi đã mất quá nhiều thời gian để giải quyết vấn đề này và không thể tìm ra giải pháp khả thi.

Hy vọng điều này sẽ hữu ích!

EDIT: tôi quên đề cập, thay đổi theo yêu cầu API từ

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

để

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

được một cái gì đó tôi cũng đã làm, và nó làm cho một sự khác biệt. :)

+0

gọi '$ facebook-> setExtendedAccessToken();' đã làm việc cho tôi, cảm ơn. – Eldar

+0

tôi đã có một ứng dụng có trang web tại các tiện ích con và khung nội tuyến tại/widgets. ngoài những thay đổi của bạn trong cơ sở facebook, tôi cũng đã phải tạo một ứng dụng mới cho các widget iframe trong/widget. bây giờ phiên trên miền gốc có vẻ ổn. –

+0

Tôi lấy lại điều đó, các phiên là tốt, nhưng người dùng vẫn đang trở về 0 sau khi trang không hoạt động trong vài phút. –

0

Có thể vì Facebook PHP SDK không phải là ajax và chúng tôi đang sử dụng các trang PHP và máy chủ của chúng tôi tải nhanh hơn quy trình xác thực từ Facebook để đọc lại phiên hợp lệ. những gì Facebook PHP SDK yêu cầu là một cái gì đó để làm mới trang trên xác nhận phiên từ các ứng dụng của chúng tôi, điều này nên được xây dựng trong SDK Javascript Facebook nhưng có vẻ như nó không phải là.

Các vấn đề liên quan