我正在開發一個使用CakePHP,Auth組件,WebTechNick的Facebook plugin和OAuth for canvas頁面(我在Facebook Developer應用程序選項中啓用了此功能)的Facebook的iFrame Canvas應用程序。我希望用戶能夠通過訪問http://apps.facebook.com/myapp/或作爲其個人資料中的選項卡將其添加到他們的個人資料(通過請求email
和publish_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
參數的過程,更重要的是如何擺脫此窗體重新提交對話框?
我的一些方法,由於過去一天的所有實驗,它們可能會有點混亂。
beforeFilter
,login
和callback
方法,在我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上的畫布應用程序的強制要求。
你說得對,該功能看起來不應該如此。當用戶未登錄時返回「未知」狀態。我只希望應用程序在用戶登錄Facebook並且未添加應用程序時重定向。當用戶已經添加了應用程序並且在用戶沒有登錄時不會重定向JS函數時,該函數不會被觸發。不幸的是,使用此函數修改表單並不能擺脫表單重新提交對話框。 – mensch