Обновление сеанса Facebook из приложения iframe

У меня есть приложение iframe для Facebook, которое является полностью внешним. Под этим я подразумеваю, что, как только пользователь обращается к URL-адресу холста для загрузки приложения, все ссылки в приложении iframe переходят на мои серверы, а страница canvas никогда не обновляется, если пользователь не перейдет в другое место на Facebook и не вернется (или обновляется браузер).

При начальной загрузке приложения, где Facebook создает iframe, я получаю все обычные параметры, такие как fb_sig_user, который позволяет мне создать сессию внутреннего приложения на основе пользователя facebook. Этот сеанс приложения (который не является сеансом Facebook, это мой собственный сеанс приложения) - все, что мне нужно, чтобы позволить пользователю работать с приложением.

Проблема возникает через час. Если пользователь покидает компьютер или использует приложение более часа, сеанс Facebook истекает. Существуют некоторые страницы приложений, для которых требуется получение информации о друге, и как только сеанс FB истек, эти страницы ломаются, выкидывая ошибки, такие как "Ошибка: ключ сеанса недействителен или больше не действителен".

Мой вопрос заключается в том, есть ли способ обновить сеанс пользователя Facebook из приложения iframe, чтобы он не истекал через час. Вызывает ли это вызов API? Есть ли трюк Facebook Connect, чтобы что-то пинговать? Есть ли какой-либо окончательный метод, чтобы сохранить его в живых? Я не смог найти примеров, специально предназначенных для этого.

Ответы

Ответ 1

Победа моя!

Существует почти полностью недокументированная функция Facebook, посвященная сессиям iframe, в которой я нашел туманную ссылку на в своих исследованиях. Однако эта страница не очень хорошо объясняет это, и только после нескольких часов просмотра различных ключей сеанса в моем iframe я смог выяснить, что происходит.

Ранее мое приложение iframe получало обычный раунд параметров fb_whatever при начальной загрузке iframe. Поэтому в моем приложении я делал это по каждому запросу:

if (isset($_REQUEST['fb_sig_session_key'])) {
    $_SESSION['fb_sig_session_key'] = $_REQUEST['fb_sig_session_key'];
}
if (! empty($_SESSION['fb_sig_session_key'])) $this->facebook->api_client->session_key = $_SESSION['fb_sig_session_key'];

Этот код получит fb_sig_session_key в первоначальной загрузке приложения, и я бы выбросил его в локальный $_SESSION для использования с API. Хранение его в локальной сессии необходимо, потому что fb_sig_session_key никогда не будет передано снова, если вы не перезагрузите все приложение iframe.

Таким образом, проблемы возникли, когда этот ключ сеанса истек более чем через час.

После просмотра неопределенной справочной страницы я начал изучать все переменные $_REQUEST, которые я получал. Оказывается, что даже по внутренней ссылке внутри вашего приложения iframe Facebook изменяет запрос на передачу по некоторым параметрам. По какой-то причине у них есть совершенно другой, но также действительный ключ сессии, который поставляется вместе с каждым запросом iframe!

Этот параметр назван в честь вашего api-ключа Facebook. Поэтому, если ваш ключ API приложения "xyz123", каждый запрос внутри вашего iframe получает параметр под названием xyz123_session_key (а также несколько других, например xyz123_expires и xyz123_user).

После просмотра связанного времени истечения основного сеанса (оригинала fb_sig_session_key) и этого сеанса только iframe (xyz123_session_key) появился свет в конце туннеля: сеанс iframe время истечения ключа фактически обновляется иногда. Я не определял, когда и как (я предполагаю, что это Ajax-пинг в какой-то момент), но тем не менее он обновляется.

Я ожидал истечения срока действия оригинального сеанса fb_sig_session_key, и, конечно же, страницы, связанные с друзьями в моем приложении, начали кашлять. В этот момент я переключил свой локально сохраненный ключ сеанса на новый iframe-only xyz123_session_key, и проблема была решена. Эта сессия работает так же хорошо, как и оригинал!

Итак, мое окончательное исправление кода заключается в том, чтобы локально сохранить ключ сеанса следующим образом:

$iframeSessionKeyName = $CONFIG['facebook']['apiKey'] . '_session_key';
if (isset($_REQUEST[$iframeSessionKeyName])) {
    $_SESSION['fb_sig_session_key'] = $_REQUEST[$iframeSessionKeyName];
}
else if (isset($_REQUEST['fb_sig_session_key'])) {
    $_SESSION['fb_sig_session_key'] = $_REQUEST['fb_sig_session_key'];
}
if (! empty($_SESSION['fb_sig_session_key'])) $this->facebook->api_client->session_key = $_SESSION['fb_sig_session_key'];

Это дает предпочтение клавише "iframe only".

Изменить: Мое первоначальное предположение о том, что ключ "iframe only" был обновлен с помощью какого-то метода Ajax, был неправильным, оказывается, что эти значения установлены в cookie от Facebook. Это приводит к некоторым междоменным проблемам при использовании этих файлов cookie. Настройка политика файла cookie P3P позволит устранить это в большинстве браузеров, кроме Safari. Safari не работает.

Ответ 2

Просто поместите

header('P3P: CP="CAO PSA OUR"');

поверх вашей страницы, и вы не потеряете сессию в iframe.

Я также заметил, что эта нить хороша 2 с половиной года. Я просто наткнулся на использование Google. Может быть, мой пост поможет кому-то другому, кто сталкивается с этим.