背景信息:我们有一个在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 framehttps://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);
}

10-07 17:24
查看更多