代码之家  ›  专栏  ›  技术社区  ›  Andy

js-将应用程序移动到子域时发生跨源安全错误(2018)

  •  2
  • Andy  · 技术社区  · 6 年前

    背景信息:我们有一个运行在 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 . 此弹出窗口中的大多数功能按预期工作。但是,当试图在弹出窗口中使用“保存”按钮时,我的浏览器控制台显示:

    未注意的圆顶异常:用原点阻塞了一个框架“ 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() 函数用于从 APP2 进入之内 https://system.example.com/app10/manage.php 基于 Javascript window.open pass values using POST -这很管用。

    问题 在弹出窗口中单击“保存”按钮时发生,该按钮在弹出窗口中呈现以下标记:

    <!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 . 由于 window.close();

    尽管我读过关于使用 postMessage 我不明白这是怎么回事,也不知道这是否是解决我问题的正确方法?正在从子域中发布数据 https://app2.example.com网站 https://system.example.com/app10 正确地。问题是 文件回调管理() 不会因为跨来源限制而开火。在我的代码中 https://app2.example.com网站 我有一个简单的陈述,看看它是否在开火:

    function filesCallbackManage(data)
    {
        console.log('filesCallbackManage has fired');
    }
    

    这不会因为我的问题而发生。我得到了前面提到的控制台错误和一个空白的弹出窗口(技术上这是正确的,因为在 <body> 但窗口不会关闭,回调也不会被触发。

    Mozilla网站上给出的示例不够广泛,无法理解如何适应这种情况。有人能详细说明一下吗?此外,链接的so帖子已经4年了,所以我想确保我在这上面的任何东西都是安全的和最新的。

    任何帮助都将不胜感激。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Quentin    6 年前

    函数的作用是传递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);
    }