javascript - postMessage to sandboxed iframe,为什么收件人窗口来源为null?

时间:2017-06-15 11:08:00

标签: javascript html iframe sandbox postmessage

2 postMessage调用测试:1使用星号表示targetOrigin,其中一个使用父文档和子文档的相同https网址。

按钮1:

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

按钮2:

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

父html文档中的iframe元素,它指向同一域中的子html文件,位于同一目录中:

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

在单击按钮以触发postMessage之前,两个文档都已完全加载。

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

如上所述编写iframe元素,按钮1对子iframe执行postMessage并成功触发子级的postMessage侦听器(尽管它使用asOisk用于targetOrigin,我不想这样做。但是,按钮2会在控制台中导致以下错误:

  

&#34;无法在'DOMWindow'上执行'postMessage':目标原点   提供的('https://myurl.net')与收件人窗口不匹配   origin('null')。&#34;

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

如果我添加&#34;允许同源&#34;对于iframe的沙盒参数,两个按钮都会成功传递postMessage数据(没有&#34; null&#34;按钮2 postMessage调用时出错,并为targetOrigin提供了url。)但是,我没有&#39 ; t想要这样做,因为我正在使用iframe的沙盒行为阻止iframe内容调用父文档中的js函数。这是一个允许&#34;任意&#34;内容(html / js / images / pdfs - 没有像php这样的服务器可执行文件)加载到子iframe中。

也许值得注意的是,iframe内容中的postMessage到父文档的类似按钮工作得很好,无论allow-same-origin参数还是asterisk / url的存在:

我构成按钮1:

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

iframed按钮2:

parent.postMessage( messageData , '*' ); 

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

所以,如果我不添加&#34; allow-same-origin&#34;为什么postMessage从父级到iframe会导致上面的错误? (为什么这个问题不会影响到父母的iframe postMessage)?我尝试将iframe src设置为child.html文档的绝对https网址,但结果是相同的。我还在不同的非ssl-cert服务器位置测试了相同的代码,并且得到了相同的结果(所以不要认为它是https贡献...)。我必须使用asterisk作为targetOrigin,并且/或者在沙箱参数中使用allow-same-origin吗?

关于这个问题的其他关于SO的谈话似乎是无止境的,所以希望能够对解决方案有新的看法......

1 个答案:

答案 0 :(得分:0)

问题是由<iframe>本身及其sandbox属性引起的:

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

根据Mozilla开发人员网络文档on this element,以下内容提出了关于同源策略的问题:

  

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>

就是这样!