背景信息:我们有一个在https://system.example.com
上运行的平台。这个平台由10个独立的web应用程序组成(都是用PHP和JS编写的)。每个应用程序以前都在同一子域中的一个子目录中:https://system.example.com/app1/
https://system.example.com/app2/
...https://system.example.com/app10/
我们正在重建其中一个应用程序app2
,并已决定将其托管在一个新的独立子域https://app2.example.com
。app2
应用程序的一部分使用JavaScript打开app10
的弹出窗口。此弹出窗口中的大多数功能按预期工作。但是,当试图在弹出窗口中使用“保存”按钮时,我的浏览器控制台显示:
未捕获的DOMException:阻止原点为“https://app2.example.com”的帧访问交叉原点帧。
在https://system.example.com/app10/manage.php:1:334
我读过SecurityError: Blocked a frame with origin from accessing a cross-origin frame和https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage两本书,但仍不清楚如何解决这个问题。
我的代码和流程如下:
弹出窗口由一个具有https://app2.example.com
事件处理程序的按钮从onclick
打开:
<button onclick="postToPopUp('https://system.example.com/app10/manage.php', 'fileManage', 'width=800px,height=600px', ['f_id', '123'], 'app2', 'filesCallbackManage')">Open app10</button>
postToPopup()
函数用于根据Javascript window.open pass values using POST将POST数据从app2
传递到https://system.example.com/app10/manage.php
-这工作正常。当我在弹出窗口中单击“保存”按钮时,出现问题,该按钮在弹出窗口中呈现以下标记:
<!doctype HTML><html><head><title>upload</title>
<script type="text/javascript" language="javascript" charset="utf-8">
var fileObject = {"files":{"0":{"f_id":"1784","f_title":"test07.pdf"},"f_id":123}};
window.opener.filesCallbackManage(fileObject);
window.close();
</script><body></body></html>
当所有东西都在同一个子域下时,它最初的作用被称为js函数
filesCallbackManage()
,它位于https://system.example.com/app2
的代码中。函数本身被传递给一个对象fileObject
,它更新了app2
中UI的各个部分。由于window.close();
虽然我读过关于使用
postMessage
的文章,但我不明白这是如何适用的,或者这是否是解决我问题的正确方法?数据正正确地从子域https://app2.example.com
发布到https://system.example.com/app10
。问题是,filesCallbackManage()
不会因为交叉源限制而触发。在https://app2.example.com
的代码中,我有一个简单的语句来查看它是否正在触发:function filesCallbackManage(data)
{
console.log('filesCallbackManage has fired');
}
这不会因为我的问题而发生。我得到了前面提到的控制台错误和一个空白的弹出窗口(技术上这是正确的,因为上面标记中的
<body>
标记中没有任何内容),但是窗口没有关闭,回调也没有被触发。Mozilla网站上给出的示例不够广泛,无法理解如何适应这种情况。有人能详细说明一下吗?此外,链接堆栈溢出post已经有四年历史了,所以我想确保我在上面放置的任何内容都是安全的和最新的。
最佳答案
函数的作用是传递POST数据
跨来源提交表单是可以的。所以你可以这么做。
当我在弹出窗口中单击“保存”按钮时,问题就出现了
您正在尝试跨源访问窗口的DOM。这是禁止的。
虽然我读过关于使用postMessage的文章,但我不明白这是如何适应的,或者这是否是解决我问题的正确方法?postMessage
尽可能接近跨原点访问窗口的DOM。
你不能这么做。
var fileObject = {"files":{"0":{"f_id":"1784","f_title":"test07.pdf"},"f_id":123}};
window.opener.filesCallbackManage(fileObject);
相反,您必须发送消息:
window.opener.postMessage(fileObject, "https://system.example.com");
并拥有监听它的代码:
addEventListener("message", receiveMessage);
function receiveMessage(event) {
if (event.origin !== "http://app2.example.com") { return false; }
filesCallbackManage(event.data);
}