javascript - postMessage для изолированного iframe, почему источник окна получателя равен нулю?

В тесте 2 вызова postMessage: 1 с использованием звездочки для targetOrigin, один с одним и тем же URL-адресом https как для родительского, так и для дочернего документов.

кнопка 1:

$('.iframed')[0].contentWindow.postMessage( messageData , '*' );

кнопка 2:

$('.iframed')[0].contentWindow.postMessage( messageData , 'https://myurl.net' );

элемент iframe в родительском html-документе, который указывает на дочерний html-файл в том же домене, в том же каталоге:

<iframe name="childFrame" class="iframed" src="child.html" sandbox="allow-scripts"></iframe>

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

==========================================

с элементом iframe, написанным, как указано выше, кнопка 1 выполняет postMessage для дочернего iframe и успешно запускает прослушиватель postMessage дочернего элемента (хотя он использует звездочку для targetOrigin, чего я бы предпочел не делать.) Однако кнопка 2 приводит к следующему ошибка в консоли:

«Не удалось выполнить 'postMessage' в 'DOMWindow': указанное целевое происхождение ('https://myurl.net') не совпадает с источником окна получателя ('null') ".

==========================================

если я добавляю «allow-same-origin» к параметрам песочницы iframe, обе кнопки затем успешно передают данные postMessage (нет ошибки «null» при вызове postMessage кнопки 2 с URL-адресом, предоставленным для targetOrigin.) однако я не Я не хочу этого делать, так как я использую поведение песочницы iframe, чтобы заблокировать содержимое iframe от вызова функций js в родительском документе. это для системы, позволяющей загружать "произвольный" контент (html / js / images / pdfs - хотя ничего исполняемого на сервере, как php) в дочерний iframe.

возможно, следует отметить, что аналогичные кнопки внутри содержимого iframe, которые отправляют сообщение в родительский документ, работают нормально, независимо от параметра allow-same-origin или наличия звездочки / URL:

Я обрамил кнопку 1:

parent.postMessage( messageData , 'https://myurl.net' ); 

Кнопка iframed 2:

parent.postMessage( messageData , '*' ); 

==========================================

Итак, почему postMessage от родительского элемента к iframe приводит к указанной выше ошибке, если я не добавляю «allow-same-origin» (и почему эта проблема не влияет на postMessage iframe для родительского элемента)? Я попытался установить для iframe src абсолютный URL-адрес https для документа child.html, но результаты были такими же. Я также протестировал тот же код на другом сервере, отличном от ssl-cert, и получил те же результаты (так что не думайте, что это способствует https ...). ДОЛЖЕН я использовать ЛИБО звездочку в качестве targetOrigin, И / ИЛИ использовать allow-same-origin в параметрах песочницы?

другие разговоры об этой проблеме на SO кажутся тупиковыми, поэтому мы надеемся получить новый взгляд на решение ...


person Crite    schedule 15.06.2017    source источник
comment
Вы это исправили? У меня точно такая же проблема.   -  person Yeti    schedule 05.03.2018
comment
Привет, Йети. Вы исправили это? (: Прошло много времени.   -  person Andy    schedule 19.03.2019


Ответы (1)


Проблема создается самим <iframe> с его атрибутом sandbox:

<iframe name="childFrame" class="iframed" src="child.html" sandbox="allow-scripts"></iframe>

Согласно документации Mozilla Developer Network об этом элементе , следующее дает проблему с политикой одинакового происхождения:

allow-same-origin: Если этот токен не используется, ресурс рассматривается как происходящий из особого источника, который всегда не соответствует политике одного и того же происхождения.

Вы не указали allow-same-origin, это означает, что кадр обрабатывается как полученный из особого источника, и postMessage вызовы этого кадра завершатся ошибкой.

Чтобы решить эту проблему, просто добавьте allow-same-origin к атрибуту sandbox, например:

<!-- index.html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<iframe name="childFrame" class="iframed" src="child.html" sandbox="allow-scripts allow-same-origin"></iframe>
<button class="btn1">A</button>
<button class="btn2">B</button>

<script>
$('.btn1').click(function(event) {
    // This works!
    $('.iframed')[0].contentWindow.postMessage( "something" , '*' );
});
$('.btn2').click(function(event) {
    // This will work too
    $('.iframed')[0].contentWindow.postMessage( "whatever you want" , 'https://myurl.net' );
});
</script>
<!-- child.html -->
<script type="text/javascript">
    window.onmessage = function(event) {
        console.log(event.data);
    }
</script>

Вот и все!

person Maxime Launois    schedule 04.05.2019