将应用程序移动到子域时出现跨域安全错误 (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');

由于我遇到的问题,这永远不会触发。我收到前面提到的控制台错误和一个空白的弹出窗口(从技术上讲,这是正确的,因为上述标记中的 &lt;body&gt; 标记中没有任何内容)但该窗口没有关闭并且没有触发回调。

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] 错误

访问静态文件时出现跨域请求错误

从 html 调用本地节点服务时出现跨源错误

本地数据访问时出现跨域问题Cross origin requests are only supported for protocol schemes: ……

尝试为标签控件赋值时出现跨线程操作错误[重复]

跨域问题和django中实现跨域