- PVSM.RU - https://www.pvsm.ru -
Во время прикручивания облачных хранилищ к скрипту для бэкапа, встала необходимость использовать OAuth 2 авторизацию, для использования с разными облачными API. В принципе с самой авторизацией никаких сложностей не возникло, но проблема возникла в немного неожиданном месте.
Учитывая аудиторию использующую софтину, было решено отказаться от поддержки древних браузеров, и всё затачивалась под современные браузеры, использующие HTML5, которые казалось бы уже вполне неплохо и одинаково поддерживают страндарты.
Но не тут-то было…
Как оказалось кроссдоменное (когда страницы с разных доменов) общение между окнами/вкладками браузера с помощью postMessage возможно только в Chrome и Firefox (проверено в Chrome 30 и Firefox 25).
В IE postMessage работает только при использовании frame/iframe (включая IE 11).
Opera неожиданно удивила. В версии 12 всё работает нормально. А вот в Opera 17, которая сделана на том же движке, что и Chrome, ведет себя по другому. Если домены отличаются, то postMessage работает только в frame/iframe, и не работает в отдельных окнах/вкладках. Если домены, точнее origin (т.е. протокол + домен + порт) совпадают, то тогда работают сообщения, как между фреймами, так и между окнами/вкладками.
Казалось бы, если все браузеры поддерживают кроссдоменное общение между фреймами, так почему бы сразу в приложении не открыть окно для авторизации в iframe? Но тут подножку ставит заботливый CORS [1] – практически на всех OAuth серверах запрещено открытие страницы авторизации в фрейме.
Не смотря на страшное название, это обычный iframe загруженный с сайта приложения, и его задача передавать полученные токены в окно приложения, так как напрямую нельзя передать из-за ограничений в Opera и IE.
После того как были испробованы различные варианты, я остановился на следующем довольно простом решении для получения токена.
Для удобства используем следующие определения:
Итого у нас используется 3 домена: domain1 – где находится приложение пользователя, domain2 — прокси-фрейм и сайт приложения, domain3 — OAuth-сервер.
Процедура получения токена выглядит так:
Не спец я, правда, по красивым схемам. Но надеюсь будет понятно.
На этой странице вы можете посмотреть живой пример [2], разве что сама OAuth-авторизация имитируется, чтобы не задергали реальный сервер.
В обычном режиме передача токена происходит так быстро, что страницы с текстовым полем не видно (она быстро закрывается). Поэтому, кто хочет увидеть более подробно, вот пример, в котором окно закрывается с задержкой в 5 секунд [3].
learn.javascript.ru/cross-window-messaging-with-postmessage [4]
javascript.ru/ajax/cross-origin-2 [5]
html5demos.com/postmessage2 [6]
habrahabr.ru/post/120336/ [7]
caniuse.com/#search=postmessage [8]
P.S. Если заинтересует могу выложить в архиве исходники скриптов из демки.
Автор: zapimir
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/45353
Ссылки в тексте:
[1] CORS: http://ru.wikipedia.org/wiki/Cross-origin_resource_sharing
[2] На этой странице вы можете посмотреть живой пример: http://zapimir.net/habr/myapp.php
[3] пример, в котором окно закрывается с задержкой в 5 секунд: http://zapimir.net/habr/myapp.php?hold=1
[4] learn.javascript.ru/cross-window-messaging-with-postmessage: http://learn.javascript.ru/cross-window-messaging-with-postmessage
[5] javascript.ru/ajax/cross-origin-2: http://javascript.ru/ajax/cross-origin-2
[6] html5demos.com/postmessage2: http://html5demos.com/postmessage2
[7] habrahabr.ru/post/120336/: http://habrahabr.ru/post/120336/
[8] caniuse.com/#search=postmessage: http://caniuse.com/#search=postmessage
[9] Источник: http://habrahabr.ru/post/197038/
Нажмите здесь для печати.