将应用程序移动到子域时出现跨域安全错误 (2018)
Posted
技术标签:
【中文标题】将应用程序移动到子域时出现跨域安全错误 (2018)【英文标题】:Cross-origin security error when moving an application to a subdomain (2018) 【发布时间】:2019-05-12 08:15:44 【问题描述】:背景信息:我们有一个在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()
函数用于将 POST 数据从 app2
传递到基于 Javascript window.open pass values using POST 的 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 网站上给出的示例不够广泛,无法理解如何适应这种情况。请问有人可以详细说明吗?此外,链接的 Stack Overflow 帖子已有四年历史,因此我想确保我在此发布的任何内容都是安全且最新的。
【问题讨论】:
【参考方案1】:postToPopup()函数用于传递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);
【讨论】:
以上是关于将应用程序移动到子域时出现跨域安全错误 (2018)的主要内容,如果未能解决你的问题,请参考以下文章
使用 .getJSON 获取 Play 商店应用详细信息时出现跨域阻止请求 [CORS] 错误
本地数据访问时出现跨域问题Cross origin requests are only supported for protocol schemes: ……