Spec-Zone.ru › Web APIs

Окно: метод postMessage()

Базовая Широко доступна

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

  • Подробнее
  • Полная совместимость
  • Отправить отзыв

Метод window.postMessage() безопасно позволяет осуществлять междоменную коммуникацию между объектами Window; например, между страницей и всплывающим окном, которое она создала, или между страницей и iframe, вставленным в неё.

Обычно скрипты на разных страницах могут обращаться друг к другу только в том случае, если страницы имеют один и тот же источник (также известный как «политика одного источника»). window.postMessage() предоставляет управляемый механизм для безопасного обхода этого ограничения (если он используется правильно).

Кроме того, скрипт, осуществляющий доступ, должен предварительно получить объект окна целевого документа. Это можно сделать с помощью методов, таких как window.open() для всплывающих окон или iframe.contentWindow для iframe.

В общем случае, одно окно может получить ссылку на другое (например, через targetWindow = window.opener), а затем отправить событие MessageEvent с targetWindow.postMessage(). Затем получающее окно свободно может обработать это событие по мере необходимости. Аргументы, переданные в window.postMessage() (т.е., «сообщение»), доступны получающему окну через объект события.

Синтаксис

postMessage(message)
postMessage(message, targetOrigin)
postMessage(message, targetOrigin, transfer)

postMessage(message, options)

Параметры

message

Данные, которые будут отправлены другому окну. Данные сериализуются с помощью алгоритма структурированного клонирования. Это значит, что вы можете безопасно передавать разнообразные объекты данных целевому окну без необходимости их самостоятельной сериализации.

targetOrigin Необязательно

Указывает источник получающего окна, необходимого для получения события. Для отправки события источник должен точно совпадать (включая схему, имя хоста и порт). Если опущено, по умолчанию используется источник вызывающего метода. Этот механизм позволяет контролировать, куда отправляются сообщения; например, если postMessage() использовался для передачи пароля, было бы крайне важно, чтобы этот аргумент был URI, источник которого совпадает с предполагаемым получателем сообщения, содержащего пароль, чтобы предотвратить перехват пароля злоумышленником. * также может быть предоставлен, что означает, что сообщение может быть отправлено обработчику с любым источником.

Примечание: Всегда указывайте конкретный targetOrigin, а не *, если вы знаете, где должен находиться документ другого окна. Отсутствие конкретного целевого источника может раскрыть данные злоумышленному сайту.

transfer Необязательно

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

options Необязательно

Необязательный объект, содержащий следующие свойства:

transfer Необязательно

Имеет то же значение, что и параметр transfer.

targetOrigin Необязательно

Имеет то же значение, что и параметр targetOrigin.

Возвращаемое значение

Ничего (undefined).

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

Объект window может слушать отправленные сообщения, выполняя следующий JavaScript:

window.addEventListener(
  "message",
  (event) => {
    if (event.origin !== "http://example.org:8080") return;

    // …
  },
  false,
);

Свойства отправленного сообщения:

data

Объект, переданный из другого окна.

origin

Источник окна, отправившего сообщение в момент вызова postMessage. Эта строка является конкатенацией протокола и "://", имени хоста, если оно существует, и ":" с номером порта, если порт присутствует и отличается от стандартного порта для данного протокола. Примеры типичных источников — https://example.org (что подразумевает порт 443), http://example.net (что подразумевает порт 80) и http://example.com:8080. Обратите внимание, что этот источник не гарантирует текущего или будущего источника этого окна, которое может перейти на другую страницу с момента вызова postMessage.

source

Ссылка на объект window окна, отправившего сообщение; это позволяет наладить двустороннее общение между двумя окнами с разными источниками.

Вопросы безопасности

Если вы не ожидаете получать сообщения с других сайтов, не добавляйте обработчики событий для событий message. Это совершенно надежный способ избежать проблем с безопасностью.

Если вы ожидаете получать сообщения с других сайтов, всегда проверяйте личность отправителя, используя свойства origin и, возможно, source. Любое окно (включая, например, http://evil.example.com) может отправлять сообщение любому другому окну внутри иерархии iframe сверху вниз каждого iframe ниже текущего документа. Однако после проверки личности вы все равно должны всегда проверять синтаксис полученного сообщения. В противном случае, уязвимость на сайте, которому вы доверяете для отправки только доверенных сообщений, может открыть XSS-уязвимость на вашем сайте.

Всегда указывайте точный целевой источник, а не *, при использовании postMessage для отправки данных другим окнам. Злоумышленный сайт может изменить расположение окна без вашего ведома, и, следовательно, он может перехватить данные, отправленные с помощью postMessage.

Безопасная передача сообщений с использованием совместной памяти

Если postMessage() выбрасывает исключение при использовании с объектами SharedArrayBuffer, вам может потребоваться убедиться, что ваш сайт должным образом изолирован от других сайтов. Доступ к совместной памяти ограничен двумя заголовками HTTP:

  • Cross-Origin-Opener-Policy со значением same-origin (защищает ваш источник от злоумышленников)
  • Cross-Origin-Embedder-Policy со значением require-corp или credentialless (защищает жертвы от вашего источника)
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Чтобы проверить, была ли междоменная изоляция успешной, вы можете проверить свойство Window.crossOriginIsolated, доступное для контекстов окон и рабочих потоков:

const myWorker = new Worker("worker.js");

if (crossOriginIsolated) {
  const buffer = new SharedArrayBuffer(16);
  myWorker.postMessage(buffer);
} else {
  const buffer = new ArrayBuffer(16);
  myWorker.postMessage(buffer);
}

Примеры

/*
 * In window A's scripts, with A being on http://example.com:8080:
 */

const popup = window.open(/* popup details */);

// When the popup has fully loaded, if not blocked by a popup blocker:

// This does nothing, assuming the window hasn't changed its location.
popup.postMessage(
  "The user is 'bob' and the password is 'secret'",
  "https://secure.example.net",
);

// This will successfully queue a message to be dispatched to the popup, assuming
// the window hasn't changed its location.
popup.postMessage("hello there!", "http://example.com");

window.addEventListener(
  "message",
  (event) => {
    // Do we trust the sender of this message? (might be
    // different from what we originally opened, for example).
    if (event.origin !== "http://example.com") return;

    // event.source is popup
    // event.data is "hi there yourself! the secret response is: rheeeeet!"
  },
  false,
);
/*
 * In the popup's scripts, running on http://example.com:
 */

// Called sometime after postMessage is called
window.addEventListener("message", (event) => {
  // Do we trust the sender of this message?
  if (event.origin !== "http://example.com:8080") return;

  // event.source is window.opener
  // event.data is "hello there!"

  // Assuming you've verified the origin of the received message (which
  // you must do in any case), a convenient idiom for replying to a
  // message is to call postMessage on event.source and provide
  // event.origin as the targetOrigin.
  event.source.postMessage(
    "hi there yourself! the secret response " + "is: rheeeeet!",
    event.origin,
  );
});

Примечания

Любой скрипт в документе в окне может запросить отправку сообщения в документ в другом окне, объект окна которого он получил, вызвав .postMessage() для этого объекта окна. Соответственно, любой обработчик событий, используемый для получения сообщений, **обязательно** должен сначала проверить идентичность отправителя сообщения, используя свойства origin и возможно source. Это нельзя переоценить: **Отказ от проверки свойств origin и возможно source позволяет проводить атаки типа межсайтового скриптинга.**

Как и в случае с любым асинхронно отправленным скриптом (таймауты, события, сгенерированные пользователем), вызывающий postMessage не может обнаружить, когда обработчик событий, прослушивающий события, отправленные postMessage, вызывает исключение.

После вызова postMessage(), MessageEvent будет отправлен только после завершения всех ожидающих контекстов выполнения. Например, если postMessage() вызывается в обработчике событий, этот обработчик будет выполнен до конца, как и все оставшиеся обработчики для того же события, прежде чем будет отправлен MessageEvent.

Значение свойства origin отправленного события не зависит от текущего значения document.domain в вызывающем окне.

Только для имен хостов IDN значение свойства origin не является согласованно Unicode или punycode; для наибольшей совместимости проверяйте и IDN, и punycode значения при использовании этого свойства, если вы ожидаете сообщения с сайтов IDN. Это значение в конечном итоге будет согласованно IDN, но пока вы должны обрабатывать оба формата IDN и punycode.

Значение свойства origin, когда отправляющее окно содержит javascript: или data: URL, является происхождением скрипта, который загрузил URL.

Использование window.postMessage в расширениях Нестандартно

window.postMessage доступен JavaScript, выполняющемуся в коде браузера (например, в расширениях и привилегированном коде), но свойство source отправленного события всегда null в качестве меры безопасности. (Другие свойства имеют ожидаемые значения.)

Контент-скрипты или скрипты веб-контекста не могут указать targetOrigin для прямого взаимодействия с расширением (либо с фоновым скриптом, либо с контент-скриптом). Скрипты веб- или контент-скрипты *могут* использовать window.postMessage с targetOrigin значения "*" для широковещательной рассылки всем обработчикам, но это не рекомендуется, так как расширение не может быть уверенным в происхождении таких сообщений, и другие обработчики (включая те, которые вы не контролируете) могут их принимать.

Контент-скрипты должны использовать runtime.sendMessage для взаимодействия с фоновым скриптом. Скрипты веб-контекста могут использовать пользовательские события для взаимодействия с контент-скриптами (с случайными именами событий, если это необходимо, чтобы предотвратить перехват гостевой страницы).

Наконец, отправка сообщения на страницу с file: URL в настоящее время требует, чтобы аргумент targetOrigin был "*". file:// не может использоваться как мера безопасности; это ограничение может быть изменено в будущем.

Спецификации

Спецификация
HTML
# dom-window-postmessage-options-dev

Совместимость с браузерами

Рабочие столы Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на iOS Samsung Internet WebView Android
postMessage 2 12
3["Firefox 8 и выше поддерживает отправку File и FileList объектов между окнами. Это разрешено только в том случае, если основной компонент получателя находится в основном компоненте отправителя по соображениям безопасности.", "До Firefox 6 параметр message должен быть строкой. С Firefox 6 параметр message сериализуется с помощью алгоритма структурированного клонирования. Это означает, что вы можете безопасно передать широкий спектр объектов данных в целевое окно, не сериализуя их самостоятельно."]
9.5 4 18
4["Firefox для Android 8 и выше поддерживает отправку File и FileList объектов между окнами. Это разрешено только в том случае, если основной компонент получателя находится в основном компоненте отправителя по соображениям безопасности.", "До Firefox для Android 6 параметр message должен быть строкой. С Firefox для Android 6 параметр message сериализуется с помощью алгоритма структурированного клонирования. Это означает, что вы можете безопасно передать широкий спектр объектов данных в целевое окно, не сериализуя их самостоятельно."]
10.1 3.2 1.0 ≤37
options_includeUserActivation_parameter 72 79 Нет 60 Нет 72 Нет 51 Нет 11.0 72
transfer_parameter 4 12 20 ≤15 5 18 20 ≤14 4 1.0 ≤37

См. также

  • Document.domain
  • CustomEvent
  • BroadcastChannel - Для междоменного взаимодействия.

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API