如何实现 iFrame 通信以防止跨源错误?

Posted

技术标签:

【中文标题】如何实现 iFrame 通信以防止跨源错误?【英文标题】:How to implement iFrame communication to prevent from cross origin error? 【发布时间】:2018-03-25 20:56:38 【问题描述】:

我正在尝试通过 iframe 向第三方 API 发送 http 请求,以解决跨源错误“在 access-control-allow-origin 中找不到源”的问题

第三方 API 不会在响应标头中返回 Origin,它们也不接受 JSONP http 请求,因此我尝试使用 iFrame 来实现它。 我正在测试简单的 html 表单以查看它是否有效。下面我有父子html。我的 Web 应用程序同时拥有父级和子级。父母向孩子发送消息 使用 postMessage 然后子级向指定的 url 发出 GET 请求并尝试将响应发布给父级。

当我运行此程序时,我在网络选项卡中看到来自第三方的响应,但浏览器仍阻止将其发送到 iFrame (child.html)。谁能指出我在这里缺少什么? 我想我需要将 iFrame 定位为与第三方相同的域。 谢谢你的建议。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>postMessage Demo: Parent</title>

    <script type="text/javascript">
        window.onload = function () 
            var receiver = document.getElementById("ifrmChild").contentWindow;

            var btn = document.getElementById('send');

            function sendMessage(e) 
                e.preventDefault();
                receiver.postMessage('https://test.computing.com/my-pay/MyPay.do?UserID=8888&Amount=100&Name=Test', '*');
            

            btn.addEventListener('click', sendMessage);
           
            function ReceiveMessage(evt) 
                alert(evt.data);
            
			
			window.addEventListener("message", ReceiveMessage, false);
        
    </script>
</head>
<body>

    <iframe id="ifrmChild" src="receiver.html" frameborder="0"  >
    </iframe>
    <br />

    <p>
        <button id="send">Send Message</button>
    </p>

</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>Child</title>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

    <script type="text/javascript">

        window.onload = function () 

            var messageEle = document.getElementById('message');

            function receiveMessage(evt) 
                messageEle.innerHTML = "Message Received: " + evt.data;

                    $.ajax(
                        url: evt.data,
                        type: 'GET',
                        success: function (data, textStatus, jqXHR) 
                            console.log(data);
                            evt.source.postMessage(data, "*");
                        ,
                        error: function (jqXHR, textStatus, errorThrown) 
                            console.log(textStatus + " " + errorThrown);
                            evt.source.postMessage(textStatus, "*");
                        
                    );
            

            // Setup an event listener that calls receiveMessage() when the window
            // receives a new MessageEvent.
            window.addEventListener('message', receiveMessage);
        
	</script>
</head>

<body style="background-color: gray;">
    <h1>Receiver</h1>
    <div id="message"></div>
</body>

</html>

【问题讨论】:

无法绕过浏览器内部的 CORS。拥有不起作用的安全性有什么意义。 【参考方案1】:

这是 iFrame 中的一项安全功能,如果域不允许,则不允许劫持。 this Stack Overflow answer给出了很好的解释...

您需要控制要嵌入的域才能删除/修改其 CORS 政策。如果域已明确阻止跨域 请求,你无能为力。

这用于避免任何人劫持您想要的任何网站(您可以 在 iframe 中运行全屏 Google,并在顶部显示您的广告 Bettergoogle.com,诸如此类)。


编辑:

要克服这个问题,您必须在第三方域中使用 iframe 托管网页。或者您可以请求第三方域所有者为特定域地址(您的托管域)启用 CORS。

【讨论】:

谢谢。这是否意味着我需要将 iframe 托管在第三方域中? 是的,您必须在第三方域中使用 iframe 托管网页。或者您可以要求第三方域所有者为特定域地址(您的托管域)启用 CORS。如果您得到答案,请考虑标记问题,否则请随时进一步提问。

以上是关于如何实现 iFrame 通信以防止跨源错误?的主要内容,如果未能解决你的问题,请参考以下文章

使用内容跨源创建 iFrame [重复]

调整 iframe 大小时,如何防止 swf 刷新?

如何让jqueryEasyUI里面的dialog弹出层跳出iframe框架在最外层显示以防止拖动时部门被遮住之后无法拖动

使用window.postMessage()方法跨域通信

使用window.postMessage()方法跨域通信

使用window.postMessage()方法跨域通信