Как стать автором
Обновить

Cookies внутри iframe — проблема при создании приложения ВКонтакте/Facebook

Время на прочтение 5 мин
Количество просмотров 56K
Управление сессиями при помощи посылки cookies на сайтах стало настолько распространено, что без этого не обходится, наверное, ни один проект, требующий авторизации пользователей. Казалось бы, механизм настолько изучен, что проблемы с ним просто немыслимы.

Так считали и мы при разработке iframe-приложения для ВКонтакте.
Но после того, как приложение было разработано (разработка велась в основном в Mozilla Firefox и Google Chrome), выяснилось, что оно неработоспособно в Internet Explorer, к которому позднее присоединились последние версии Opera и Safari.

Под катом подробное описание проблемы и вариантов её решения.

Описание проблемы


Первым делом было установлено, что cookies успешно передаются сервером и принимаются браузером, но тот, в свою очередь, не сохраняет их и не передаёт назад на сервер вместе со следующими запросами.

Поведение казалось странным, однако оно имеет под собой объективное обоснование: браузер обеспечивает приватность просмотра страниц и не принимает cookies от страниц внутри iframe.

Приведу пример.
Предположим, что вы подбираете себе ноутбук и читаете web-страницы с бенчмарками и различными сравнениями ноутбуков. На каких-то из этих страниц, наверняка, будет установлен Google AdSense или какая-то другая подобная система, имеющая возможность послать вам уникальное значение посредством cookies и далее идентифицировать вас по нему. Позже, читая новости, документацию по вашему любимому фреймворку или участвуя в обсуждениях на форумах, вы будете удивлены тем, что в рекламе вам показываются предложения о покупке ноутбуков. А, тем временем, система, размещающая рекламу, повысит кому-то CTR. ;)

Браузеры пытаются защитить нас от подобного рода сбора информации и запрещают приём cookies от страниц внутри iframe.

Но мы никак не связаны с рекламой и сбором сведений, поэтому рассмотрим варианты решения проблемы.

Cookie в iframe и Internet Explorer


В нашем случае решение для Internet Explorer не заставило себя ждать: проблема рассматривалась множество раз и ответы быстро находятся в гугле.

Решением является посылка HTTP-заголовка следующего содержания:
P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"

В частности для PHP это будет выглядеть так:
<?php
header('P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');


Cookie в iframe и Opera/Safari


Проблема в этих браузерах появилась не так давно, и поэтому идентифицировать и решить её оказалось немного сложнее.

Суть проблемы в том, что в последних версиях этих браузеров по умолчанию стоят галочки «Сookies: Принимать только с посещаемого сайта» (Opera) и «Принимать cookies: Только от посещаемых сайтов» (Safari)

Очевидным решением проблемы является изменения режима приёма cookies на «всегда». Однако в большинстве случаев «попросить» сделать это всех пользователей не представляется возможным.

Поэтому попытаемся рассмотреть другие способы решения проблемы.

Способ 1. Splash Screen вместо первой страницы

Более детальное рассмотрение проблемы показало, что cookies не устанавливаются до каких-либо действий пользователя. После того, как пользователь перейдёт на другую страницу в iframe, кликнув по какой-либо ссылке, cookies начинают успешно приниматься.

Стоит обратить внимание на то, что не помогает эмуляция перехода на другую страницу. А именно:
  • редирект при помощи HTTP-заголовка Location
  • редирект при помощи соответствующего meta-тега
  • редирект при помощи изменения window.location из JavaSctipt'а
  • редирект при помощи вызова из JavaScript метода click() у ссылки

Очевидное решение: вместо реального сайта первой страницей выводить пользователю приветствие со ссылкой «перейти к приложению».

Достоинства:
+ простота, пуленепробиваемость
+ независимость от наличия включённого JavaScript в браузере

Недостатки:
— требует дополнительного действия от пользователя
— несолидность (лишняя страница с «непонятным» приветствием)

Способ 2. Редирект при помощи отправки формы

В перечисленных мною способах эмуляции перехода неспроста отсутствует редирект при помощи отправки формы.

Суть метода:
  • в iframe создаётся форма, action которой ведёт на нужную страницу текущего домена
  • форма отправляется посредством JavaScript

И этот метод работает: скрипт, расположенный по адресу action'а формы(и последующие вызываемые скрипты), успешно установит cookies.

При этом не имеет значения тот факт, будет ли отправлена форма методом GET или POST.

Пример реализации с использованием jQuery:
<script type="text/javascript">
$(function(){
	$('body').append('<form id="cookiesHackForm" action="http://example.com/" method="get"></form>');
	$('#cookiesHackForm').submit();
});
</script>


Достоинства:
+ не требует действий от пользователя

Недостатки:
— требуется JavaScript
— требуется пустая страница только лишь для редиректа

Способ 3. Отправка формы в фоне при помощи дополнительного iframe

Является развитием второго способа, в котором ликвидируется недостаток в наличии редиректа.

Для того, чтобы избежать наличия лишней пустой страницы для редиректа, мы можем создать дополнительный iframe, в который будем отправлять форму, описанную выше. Тем самым мы покажем пользователю какую-то полезную страницу, а cookies установим «в фоне».

Пример реализации с использованием jQuery:
<script type="text/javascript">
$(function(){
	$('body').append('<iframe id="cookiesHackFrame" name="cookiesHackFrame" src="http://example.com/blank.html" style="display:none;"></iframe>');
	$('body').append('<form id="cookiesHackForm" action="http://example.com/" method="post" target="cookiesHackFrame" >');
	$('#cookiesHackForm').submit();
});
</script>


Достоинства:
+ не требует действий от пользователя
+ не требуется редирект

Недостатки:
— требуется JavaScript
— не имеет смысла там, где вывод страницы должен произвестись только после установки cookies

Заключение


Браузеры заботятся о нашей приватности, но наличие обходных путей заставляет задуматься – баг ли эти пути или фича. В первом случае через некоторое время после соответствующих заплаток придётся отказаться от решения проблем такими способами. Но, пока они работают, – нет причин для отказа от пользования ими.

Ссылки по теме


http://www.w3.org/TR/P3P/#guiding_principles
http://stackoverflow.com/questions/389456/cookie-blocked-not-saved-in-iframe-in-internet-explorer
http://stackoverflow.com/questions/2691864/facebook-iframe-app-with-multiple-pages-in-safari-session-variables-not-persistin
http://developers.facebook.com/docs/best-practices#miscellaneous-issues
http://anantgarg.com/2010/02/18/cross-domain-cookies-in-safari/
http://lightyearsoftware.com/2009/11/on-the-pain-of-developing-for-facebook/
http://javascript.ru/unsorted/id (thx seriyPS)

UPD: если кто-то подскажет более подходящий блог, то буду очень признателен.
UPD2: переместил в блог Браузеры по рекомендации. (thx agul)
Теги:
Хабы:
+49
Комментарии 45
Комментарии Комментарии 45

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн