# Кросс-доменные ограничения и их обход
Ограничение "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 не включает порт в понятие источника. Кроме того, он позволяет снять ограничения для конкретного сайта включением в доверенную зону.