2011-06-21 42 views
2

我正在開發一個使用CakePHP,Auth組件,WebTechNick的Facebook plugin和OAuth for canvas頁面(我在Facebook Developer應用程序選項中啓用了此功能)的Facebook的iFrame Canvas應用程序。我希望用戶能夠通過訪問http://apps.facebook.com/myapp/或作爲其個人資料中的選項卡將其添加到他們的個人資料(通過請求emailpublish_stream權限)後使用該應用程序。如何處理Facebook的signed_request for iFrame Canvas應用程序?

請求權限不是問題。用戶被重定向到權限請求頁面,然後重定向到請求access_token的回調方法,按照此tutorial

此回調之後,用戶被重定向回http://apps.facebook.com/myapp/,它顯示了他們的個人索引頁面。這也是問題出現的地方。只要上述URI被加載,瀏覽器要求重新提交表單,每當我重新加載http://apps.facebook.com/myapp/時,都會發生這種情況。這是因爲Facebook想要通過(預期)signed_request參數,我想知道如何處理它。它不是一個空變量,所以我需要另一種驗證方法或重定向嗎?

我應該如何處理signed_request參數的過程,更重要的是如何擺脫此窗體重新提交對話框?

我的一些方法,由於過去一天的所有實驗,它們可能會有點混亂。

beforeFilterlogincallback方法,在我UserController.php:

function beforeFilter() { 
    parent::beforeFilter(); 
    if (empty($this->permissions)) { 
     $this->Auth->allow('login', 'logout', 'callback'); 
    } 
    } 

    function login() { 
    $session = $this->facebook->getSession(); 
    $login_url = 'https://graph.facebook.com/oauth/authorize?client_id=' . FACEBOOK_APP_ID . '&redirect_uri=' . MY_APP_URL . '/users/callback/&type=user_agent&&display=page&scope=' . FACEBOOK_APP_PERMISSIONS; 
    if($session){ 
     try { 
     $uid = $facebook_client->getUser(); 
     $me = $facebook_client->api('/me', $params); 
     print($me); 
     } catch (FacebookApiException $e) { 
     error_log($e); 
     } 
     } else { 
     $this->set('authorise', true); 
     $script = '$(document).ready(function() { facebookRequestPermissions("'.$login_url.'");});'; 
     $this->set('script', $script); 
     } 
    } 

    function callback() { 
    function callFb($url, $params) { 
     $ch = curl_init(); 
     curl_setopt_array($ch, array(
      CURLOPT_URL => $url, 
      CURLOPT_POSTFIELDS => http_build_query($params), 
      CURLOPT_RETURNTRANSFER => true, 
      CURLOPT_VERBOSE => true 
     )); 
     $result = curl_exec($ch); 
     curl_close($ch); 
     return $result; 
    } 

    $params=array('client_id'=>FACEBOOK_APP_ID, 'type'=>'client_cred', 'client_secret'=>FACEBOOK_APP_SECRET); 
    $url = "https://graph.facebook.com/oauth/access_token"; 
    $access_token = callFb($url, $params); 
    $access_token = substr($access_token, strpos($access_token, "=")+1, strlen($access_token)); 

    if ($access_token) { 
     $this->redirect(FACEBOOK_APP_URL); 
    } else { 
     echo 'An error has occurred'; 
    } 
    } 

中的JavaScript中的登錄方法是指這個jQuery的功能,Facebook的的JavaScript SDK被初始化在$(document).ready()

function facebookRequestPermissions(login_url) { 
    FB.getLoginStatus(function(response) { 
    if (response.status !== 'unknown') { 
     top.location.href=login_url; 
    } 
    }); 
} 

JavaScript功能只應在用戶登錄時觸發,如果不是,則會顯示不同的登錄頁面。

我用一些方法在整體AppControler:

class AppController extends Controller { 
    var $components = array('RequestHandler', 'Session', 'Auth', 'Facebook.Connect'); 
    var $helpers = array('Form', 'Time','Html','Javascript', 'Session', 'Facebook.Facebook'); 
    protected $facebook; 
    protected $permissions; 
    private $user; 

    function beforeRender() { 
    //Save the username if it isn't already present 
    if ((int)$this->Auth->user('id') != '' && (string)$this->Auth->user('username') == '') { 
     $data = array('id' => (int)$this->Auth->user('id'), 'username' => (string)$this->user['username']); 
     $this->loadModel('User'); 
     $this->User->save($data); 
    } 
    if (!empty($this->user) && !empty($this->permissions)) { 
     $this->set('currentUser', $this->Auth->user()); 
    } 
    } 

    function beforeFilter() { 
    $this->Auth->autoRedirect = false; 
    $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); 
    $this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index'); 
    $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login'); 
    App::import('Lib', 'Facebook.FB'); 
    $this->facebook = new FB(); 
    $this->user = $this->facebook->api('/me'); 
    $this->permissions = $this->facebook->api('/me/permissions'); 
    } 
} 

編輯: 這似乎只與Firefox的問題。 Chrome不會顯示該對話框,而是執行靜默刷新,之後signed_request參數爲空,這很奇怪。 Firefox不是這種情況,其中signed_request參數在每次提示刷新後都保持不變(除非iFrame內容被緩存),這似乎是無限循環的。

編輯2: 這個不斷掙扎,但是我最終禁用的OAuth 2.0在Facebook開發應用程序,它已經解決了重新提交表單問題畫布選項。當然,這不是一個真正的解決方案,因爲我相信OAuth 2.0已經成爲Facebook上的畫布應用程序的強制要求。

回答

1

由於我無法測試整個事情,我不確定這是否正確,但一見鍾情你的JavaScript函數看起來很奇怪。它看起來像你總是重定向到登錄網址,雖然用戶給予了許可。

指的Facebook JavaScript SDK,功能應該是這樣的:

function facebookRequestPermissions(login_url) { 
    FB.getLoginStatus(function(response) { 
    if (!response.session) { 
     top.location.href=login_url; 
    } 
    }); 
} 

,或者,如果你想調用.status

if (response.status == 'unknown') 

關於您關於signed_request的問題:它是用來獲取一些信息,看看Authentication - Signed Request看看究竟是什麼。你不需要另一種驗證方法。

+0

你說得對,該功能看起來不應該如此。當用戶未登錄時返回「未知」狀態。我只希望應用程序在用戶登錄Facebook並且未添加應用程序時重定向。當用戶已經添加了應用程序並且在用戶沒有登錄時不會重定向JS函數時,該函數不會被觸發。不幸的是,使用此函數修改表單並不能擺脫表單重新提交對話框。 – mensch

相關問題