postMessage() cross-origin iframe javascript
postMessage() cross-origin iframe javascript
我正在尝试使用 postMessage() 与 cross-origin 资源进行通信,但无法使其正常工作。我已经查看了其他几十个类似的问题,但仍然卡住了。
(https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage, https://javascript.info/cross-window-communication, How can I do cross-domain postMessage?, 等等)
我在同一个源上工作,但是当我移动到不同的源时,我得到一个标准的 corss-origin 错误。
Uncaught DOMException: Blocked a frame with origin ... from accessing
a cross-origin frame.
我调用了两次 postMessage()。一旦使用通配符加载页面 - 这是有效的。一旦使用了 delcared 来源 - 这是我所需要的,但无法开始工作。
Parent:
<html>
<body>
<button class="site-btn" onclick="initChatIfr();">Load Iframe</button>
<iframe lws-ifr="demo-ifr" lws-ifr-status='inactive'></iframe>
<script>
const ifrEle = document.querySelector('[lws-ifr="chat-ifr"]');
function initChatIfr() {
ifrEle.src = 'https://some-cdn.cloudfront.net/post-message/index.html';
ifrEle.setAttribute('lws-ifr-status', 'active');
}
function listener(e) {
const acceptedOrigins = ['https://some-cdn.cloudfront.net', 'https://some-sandbox.s3.amazonaws.com', 'http://localhost:3000'];
if (e.data.indexOf('close') < 0 || acceptedOrigins.indexOf(e.origin) < 0) {
console.log(' not a close event or an unapproved ifr origin')
return;
} else {
console.log(' approved ifr origin')
ifrEle.setAttribute('lws-ifr-status', 'inactive');
setTimeout(function() {
ifrEle.src = '';
},300);
}
}
if (window.addEventListener){
addEventListener("message", listener, false);
} else {
attachEvent("onmessage", listener);
}
</script>
</body>
</html>
Child:
<!DOCTYPE html>
<html>
<body>
<button class="site-btn cancel-btn" onclick="closeParentIframe();">Close Iframe</button>
<script>
const acceptedHosts = ['some-cf-cdn.cloudfront.net', 'some-sandbox-bucket.s3.amazonaws.com', 'localhost:3000'];
function closeParentIframe() {
const pOrigin = parent.origin;
const pHost = parent.location.host;
if (acceptedHosts.indexOf(pHost) > -1) {
console.log(' APPROVED parent origin', pOrigin);
parent.postMessage('close', pOrigin);
} else {
console.log(' UNAPPROVED parent origin', pOrigin);
}
}
console.log('ifr loaded');
parent.postMessage("hi from the ifr " + location.href, '*');
</script>
</body>
</html>
任何帮助将不胜感激!
看起来问题出在您的子脚本中,您正在尝试访问 parent.origin
以及 parent.location.host
,这导致了错误,因为考虑到跨源问题,这是不允许的。
如果要从子代码中获取父域,可以改用document.location.ancestorOrigins[0])
。但是,Firefox 目前似乎不支持此功能。参见 https://caniuse.com/?search=ancestorOrigin
除此之外,其他看起来还可以。
这是一个关于如何从 iFrame 获取父域的选项的讨论帖:
Access parent URL from iframe
我正在尝试使用 postMessage() 与 cross-origin 资源进行通信,但无法使其正常工作。我已经查看了其他几十个类似的问题,但仍然卡住了。
(https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage, https://javascript.info/cross-window-communication, How can I do cross-domain postMessage?, 等等)
我在同一个源上工作,但是当我移动到不同的源时,我得到一个标准的 corss-origin 错误。
Uncaught DOMException: Blocked a frame with origin ... from accessing a cross-origin frame.
我调用了两次 postMessage()。一旦使用通配符加载页面 - 这是有效的。一旦使用了 delcared 来源 - 这是我所需要的,但无法开始工作。
Parent:
<html>
<body>
<button class="site-btn" onclick="initChatIfr();">Load Iframe</button>
<iframe lws-ifr="demo-ifr" lws-ifr-status='inactive'></iframe>
<script>
const ifrEle = document.querySelector('[lws-ifr="chat-ifr"]');
function initChatIfr() {
ifrEle.src = 'https://some-cdn.cloudfront.net/post-message/index.html';
ifrEle.setAttribute('lws-ifr-status', 'active');
}
function listener(e) {
const acceptedOrigins = ['https://some-cdn.cloudfront.net', 'https://some-sandbox.s3.amazonaws.com', 'http://localhost:3000'];
if (e.data.indexOf('close') < 0 || acceptedOrigins.indexOf(e.origin) < 0) {
console.log(' not a close event or an unapproved ifr origin')
return;
} else {
console.log(' approved ifr origin')
ifrEle.setAttribute('lws-ifr-status', 'inactive');
setTimeout(function() {
ifrEle.src = '';
},300);
}
}
if (window.addEventListener){
addEventListener("message", listener, false);
} else {
attachEvent("onmessage", listener);
}
</script>
</body>
</html>
Child:
<!DOCTYPE html>
<html>
<body>
<button class="site-btn cancel-btn" onclick="closeParentIframe();">Close Iframe</button>
<script>
const acceptedHosts = ['some-cf-cdn.cloudfront.net', 'some-sandbox-bucket.s3.amazonaws.com', 'localhost:3000'];
function closeParentIframe() {
const pOrigin = parent.origin;
const pHost = parent.location.host;
if (acceptedHosts.indexOf(pHost) > -1) {
console.log(' APPROVED parent origin', pOrigin);
parent.postMessage('close', pOrigin);
} else {
console.log(' UNAPPROVED parent origin', pOrigin);
}
}
console.log('ifr loaded');
parent.postMessage("hi from the ifr " + location.href, '*');
</script>
</body>
</html>
任何帮助将不胜感激!
看起来问题出在您的子脚本中,您正在尝试访问 parent.origin
以及 parent.location.host
,这导致了错误,因为考虑到跨源问题,这是不允许的。
如果要从子代码中获取父域,可以改用document.location.ancestorOrigins[0])
。但是,Firefox 目前似乎不支持此功能。参见 https://caniuse.com/?search=ancestorOrigin
除此之外,其他看起来还可以。
这是一个关于如何从 iFrame 获取父域的选项的讨论帖: Access parent URL from iframe