Междоменная связь iframe (postMessage)

JavaScript

Междоменная связь iframe (postMessage)

предисловие

Простыми словами, кросс-доменный относится к взаимным запросам ресурсов между разными доменами, например запросам AJAX, и браузер перехватывает результат ответа в соответствии с политикой одного и того же источника, что является ограничением безопасности, налагаемым браузером на JavaScript. Так называемая гомология относится к одному и тому же доменному имени, протоколу и порту, если один из них отличается, он является междоменным.

фон спроса

Вставьте другой сторонний веб-проект через iframe в веб-проект, нажмите кнопку в стороннем веб-проекте, чтобы вызвать глобальную функцию веб-проекта в режиме реального времени, чтобы открыть глобальное всплывающее окно или выполнить переход по маршруту. В настоящее время существует два проекта. Взаимодействие данных явно нарушает политику одного и того же источника. Метод postMessage в объекте окна, представленный стандартом HTML5, позволяет сценариям из разных источников взаимодействовать асинхронно в ограниченном порядке, позволяя кросс-текстовый документ, мульти -window и обмен сообщениями между доменами.

совместимость

Можно видеть, что postMessage хорошо поддерживается в основных основных браузерах, за исключением браузеров IE с низкими версиями.

грамматика

Для получения дополнительной информации, пожалуйста, нажмите здесьMDN, вот простое объяснение каждого параметра otherWindow.postMessage(сообщение, targetOrigin, [передача]);

  • otherWindow: целевое окно (которое вы хотите отправлять междоменные сообщения), например: iframe.contentWindow
  • сообщение данные для отправки
  • targetOrigin Адрес (URL) целевого окна или строка '*' означает неограниченный, разрешено отправлять любой URL
  • передача: необязательный параметр, расширенное использование, здесь не обсуждается, представляет собой строку передаваемых объектов, передаваемых одновременно с сообщением. Право собственности на эти объекты будет передано получателю сообщения, а отправитель больше не сохранит право собственности.

использовать

Предположим, что теперь есть две страницы с разным происхождением, адрес родительской страницы:http://a.index.com, адрес подстраницы:http://b.index.com, родительская страница представляет дочернюю страницу через iframe

<!-- a.index.html -->
<h1>父页面</h1>
<iframe id="iframe" src="http://b.index.com"></iframe>

①Родительская страница отправляет сообщение дочерней странице

const iFrame = document.getElementById('iframe')
<!-- 需要等到iframe中的子页面加载完成后才发送消息,否则子页面接收不到消息 -->
iFrame.onload = function(){
  <!-- iFrame.contentWindow获取到iframe的window对象 -->
  iFrame.contentWindow.postMessage('父页面发送的消息','http://b.index.com');
}

②Дочерняя страница получает сообщение родительской страницы

有发送就有接收,与postMessage配套使用的就是message事件
window.addEventListener('message',e=>{
    <!-- 对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击 -->
    if(e.origin==='http://a.index.com'){
        console.log(e.origin) //父页面URL,这里是http://a.index.com
        console.log(e.source) // 父页面window对象,全等于window.parent/window.top
        console.log(e.data)  //父页面发送的消息
    }
},false)

③Дочерняя страница отправляет сообщение родительской странице С предыдущей основой нам нужно только помнить, что otherWindow в otherWindow.postMessage — это объект окна целевого окна, в которое вы хотите отправить данные.

window.parent.postMessage('子页面发送的消息','http://a.index.com')

④Родительская страница получает сообщение дочерней страницы Полученная логика связи такая же, как у родитель-потомок и дочерний-родительский

window.addEventListener('message',e=>{
    <!-- 对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击 -->
    if(e.origin==='http://b.index.com'){
        console.log(e.origin) //子页面URL,这里是http://b.index.com
        console.log(e.source) // 子页面window对象,全等于iframe.contentWindow
        console.log(e.data) //子页面发送的消息
    }
},false)

будь осторожен

  • Окно в window.postMessage относится к окну, которому вы хотите отправлять междоменные сообщения (целевое окно, с которым вам нужно общаться), а не к окну его собственного окна.
    • На родительской странице: родительская страница отправляет междоменную информацию на дочернюю страницу, а окно — это окно дочерней страницы, на которое указывает iframe, встроенный в родительскую страницу, а именно: iFrame.contentWindow
    • На дочерней странице: дочерняя страница хочет, чтобы родительская страница отправляла междоменную информацию, а окно — это окно родительской страницы.Здесь, поскольку дочерняя страница встроена в родительскую страницу, для дочерней страницы окно является топ или родитель.
  • Вам нужно дождаться загрузки подстраницы в iframe перед отправкой сообщения, иначе подстраница не получит сообщение
  • При прослушивании события сообщения вам необходимо определить источник сообщения