javascript - postMessage to sandboxed iframe,为什么收件人窗口来源为null? [英] javascript - postMessage to sandboxed iframe, why is recipient window origin null?
问题描述
2 postMessage调用测试:1使用asterisk作为targetOrigin,一个使用父文档和子文档的相同https url。
2 postMessage calls in the test: 1 using an asterisk for targetOrigin, one using the same https url of both the parent and child documents.
按钮1:
$('.iframed')[0].contentWindow.postMessage( messageData , '*' );
按钮2:
$('.iframed')[0].contentWindow.postMessage( messageData , 'https://myurl.net' );
父html文档中的iframe元素,它指向同一域上的子html文件,位于同一目录中:
the iframe element in parent html document, which points to child html file on same domain, in same directory:
<iframe name="childFrame" class="iframed" src="child.html" sandbox="allow-scripts"></iframe>
在单击按钮触发postMessage之前,两个文档都已完全加载。
both documents are fully loaded before I am clicking the buttons to trigger postMessage.
========================================= =
==========================================
如上所述编写iframe元素,按钮1对子iframe执行postMessage并成功触发子级的postMessage侦听器(尽管它使用星号表示targetOrigin,我我不想这样做。但是,按钮2会在控制台中导致以下错误:
with iframe element written as above, button 1 performs the postMessage to the child iframe and triggers the child's postMessage listener successfully (though it uses the asterisk for targetOrigin, which I'd prefer not to do.) however, button 2 results in the following error in console:
无法执行'postMessage' 'DOMWindow':提供的目标来源
(' https://myurl.net ')不匹配收件人窗口的
来源('null')。
"Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://myurl.net’) does not match the recipient window’s origin (‘null’)."
============ ==============================
==========================================
如果我添加允许 -same-origin到iframe的沙箱参数,然后两个按钮成功传递postMessage数据(使用为targetOrigin提供的url按钮2 postMessage调用没有null错误。)但是,我不想这样做,因为我使用iframe的沙盒行为阻止iframe内容调用js函数父文件。这是一个系统允许任意内容(html / js / images / pdfs - 没有像php这样的服务器可执行文件)加载到子iframe中。
if I add "allow-same-origin" to the iframe's sandbox parameters, both buttons then pass the postMessage data successfully (no "null" error on the button 2 postMessage call with the url provided for the targetOrigin.) however, I don't want to do this, as I am using the iframe's sandboxing behavior to block the iframe content from calling js functions in the parent document. this is for a system allowing "arbitrary" content (html/js/images/pdfs -- nothing server-executable like php though) to be loaded into the child iframe.
也许值得注意的是,iframe内容中的postMessage到父文档的类似按钮工作得很好,无论allow-same-origin参数还是asterisk / url的存在:
perhaps of note, similar buttons inside of the iframe content that postMessage to the parent document work just fine, regardless of the allow-same-origin parameter or the presence of the asterisk/url:
我框架按钮1:
parent.postMessage( messageData , 'https://myurl.net' );
iframed按钮2:
iframed button 2:
parent.postMessage( messageData , '*' );
===================== =====================
==========================================
那么,为什么postMessage从父代到iframe会导致上面的错误,如果我不添加allow-same-origin(为什么这个问题不会影响iframe postMessage到父级)?我尝试将iframe src设置为child.html文档的绝对https网址,但结果是相同的。我还在不同的非ssl-cert服务器位置测试了相同的代码,并且具有相同的结果(所以不要认为它是https贡献...)。我必须使用asterisk作为targetOrigin,并且/或者在沙箱参数中使用allow-same-origin吗?
so, why does postMessage from the parent to the iframe results in the error above if I don't add "allow-same-origin" (and why does this issue not affect the iframe postMessage to the parent)? I attempted setting the iframe src to an absolute https url to the child.html document, but results were the same. I also tested the same code on a different, non ssl-cert server location, and had the same results (so don't think it is https contributing...). MUST i have EITHER the asterisk as the targetOrigin, AND/OR use allow-same-origin in the sandbox params?
关于此问题的其他对话似乎已经死了 - 结束所以希望对解决方案有新的看法......
other conversations about this issue on SO seem to dead-end so hoping to get a new perspective on a solution...
推荐答案
问题是由< iframe>
本身,其沙箱
属性:
The problem is created by the <iframe>
itself, with its sandbox
attribute:
<iframe name="childFrame" class="iframed" src="child.html" sandbox="allow-scripts"></iframe>
根据Mozilla开发人员网络文档关于此元素,以下给出了有关同源策略的问题:
As per the Mozilla Developer Network documentation on this element, the following gives a problem about same-origin policy:
allow-same-origin
:如果未使用此令牌,则资源被视为来自特殊来源总是没有同源政策。
allow-same-origin
: If this token is not used, the resource is treated as being from a special origin that always fails the same-origin policy.
你没有指定 allow-same-origin
,这意味着该帧被视为来自特殊原点, postMessage
对该帧的调用将失败。
You didn't specified allow-same-origin
, that means the frame is treated as being from a special origin, and postMessage
calls to that frame will fail.
要解决此问题,只需将 allow-same-origin
添加到沙箱
属性,就像这样:
To solve the problem, just add allow-same-origin
to the sandbox
attribute, like this:
<!-- 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>
就是这样!
这篇关于javascript - postMessage to sandboxed iframe,为什么收件人窗口来源为null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!