# Кросс-доменные ограничения и их обход Ограничение "Same Origin" ("тот же источник") ограничивает доступ окон и фреймов друг к другу, а также влияет на AJAX-запросы к серверу. Причина, по которой оно существует -- безопасность. Если есть два окна, в одном из которых `vasya-pupkin.com`, а в другом `gmail.com`, то мы бы не хотели, чтобы скрипт из первого мог читать нашу почту. Сама концепция проста, но есть много важных исключений и особенностей, которые нужно знать для полного понимания этого правила. [cut] ## Концепция Same Origin [#same-origin] Два URL считаются имеющим один источник ("same origin"), если у них одинаковый протокол, домен и порт. Эти URL имеют один источник: - `http://site.com` - `http://site.com`/ - `http://site.com/my/page.html` А вот эти -- все из других источников: - http://www.site.com (другой домен) - http://site.org (другой домен) - https://site.com (другой протокол) - http://site.com:8080 (другой порт) Существует ряд исключений, позволяющих-таки окнам с разных доменов обмениваться информацией, но прямой вызов методов друг друга и чтение свойств запрещены. ## В действии Если одно окно попытается обратиться к другому, то браузер проверит, из одного ли они источника. Если нет -- доступ будет запрещён. Например: ```html run ``` Пример выше выведет ошибку. ## Исключение: запись в location Окна могут менять `location` друг друга, даже если они из разных источников. Причём *читать* свойства `location` нельзя, одно окно не имеет право знать, на каком URL пользователь в другом. А вот *запись* браузеры считают безопасной. Например, открыв на `javascript.ru` iframe с `http://example.com`, из этого ифрейма нельзя будет прочитать URL, а вот поменять его -- запросто: ```html run ``` Если запустить код выше, то окно сначала загрузит `example.com`, а потом будет перенаправлено на `wikipedia.org`. ## Исключение: поддомен 3-го уровня Ещё одно важное исключение касается доменов третьего уровня. Если несколько окон имеют общий домен второго уровня, к примеру `john.site.com`, `peter.site.com`, `site.com`, и присваивают в `document.domain` свой общий поддомен 2-го уровня `site.com`, то все ограничения снимаются. То есть, на всех этих сайтах должен быть код: ```js document.domain = 'site.com'; ``` Тогда между ними не будет кросс-доменных ограничений. Обратим внимание: свойство `document.domain` должно быть присвоено на всех окнах, участвующих в коммуникации. Выглядит абсурдно, но даже на документе с `site.com` нужно вызвать: `document.domain="site.com"`. Иначе не будет работать. Таким образом разные подсайты в рамках одного общего проекта могут взаимодействовать без ограничений. ## Исключения в IE В браузере Internet Explorer есть два своих, дополнительных исключения из Same Origin Policy. 1. Порт не входит в понятие "источник" (origin). Это означает, что окно с `http://site.com` может свободно общаться с `http://site.com:8080`. Это иногда используют для общения серверов, использующих один IP-адрес. Но допустимо такое только в IE. 2. Если сайт находится в зоне "Надёжные узлы", то в Internet Explorer ограничения к нему не применяются. При этом подразумевается, что для этой зоны в параметрах "Безопасность" включена опция "Доступ к источникам данных за пределами домена". ## Итого Ограничение "одного источника" запрещает окнам и фреймам с разных источников вызывать методы друг друга и читать данные друг из друга. При этом "из одного источника" означает "совпадают протокол, домен и порт". У этого подхода ряд существенных исключений: - Свойства `window.location.*` нельзя читать, но можно менять. - Домены третьего уровня с общим наддоменом могут поменять `document.domain` на их общий домен второго уровня, и тогда они смогут взаимодействовать без ограничений. - IE не включает порт в понятие источника. Кроме того, он позволяет снять ограничения для конкретного сайта включением в доверенную зону.