允许子 iframe 从不同域调用其父窗口上的函数
Posted
技术标签:
【中文标题】允许子 iframe 从不同域调用其父窗口上的函数【英文标题】:Allowing a child Iframe to call a function on its parent window from a different domain 【发布时间】:2012-10-14 02:29:04 【问题描述】:我创建了一个页面,该页面在 IFrame 中加载,它需要在完成加载后调用父页面上的函数。
它在本地开发中(在同一个域上)工作,但在现实世界中它托管在一个完全不同的域上,所以显然我遇到了跨域问题,即:
不安全的 javascript 尝试从 URL 为 http://[...]site2.com/iframe 的框架访问 URL 为 http://[...]site1.com 的框架。域、协议和端口必须匹配。
我控制了两台服务器,那么我是否可以在其中一台或两台服务器上放置一些内容,说明它们可以相互通信?
我已经查看了在 iframe 页面和父页面中设置“document.domain”。
我已经尝试过设置访问控制标头:
header('Access-Control-Allow-Origin: *');
但这些都不起作用。
当我控制两台服务器时,是否有任何方法允许 iframe 在完全不同的域上调用父窗口中的函数?
【问题讨论】:
这个post 提供了一个非常简单的解决方案。 @craned 但该帖子仅适用于同一域 【参考方案1】:您可以通过message posting API在框架之间进行通信。
例如,在您的子框架中,您可能会调用:
parent.postMessage("child frame", "*");
并在父框架中,注册一个消息处理程序:
window.addEventListener("message", function(event)
console.log("Hello from " + event.data);
);
【讨论】:
在 IE11 上测试【参考方案2】:这里有很多选项:http://softwareas.com/cross-domain-communication-with-iframes
【讨论】:
尽管顶部有一条说明,本文主要出于历史目的而保留,在现代世界中,您应该只使用postMessage
(根据公认的答案)【参考方案3】:
使用 .htaccess 重写可以轻松解决此问题。
演示:
A.在 SERVER 1 上创建一个名为“iframeContent/”的目录。
B.在该目录中放置一个名为 index.php 的文件,其中包含:
<html> <head></head> <body> <script type="text/javascript"> parent.check(); </script> </body> </html>
这是 iFrame 的内容。它将调用父级中的函数。
C.在 SERVER 2 上创建一个名为“iframeTesting_without-htaccess/”的目录。
D.在该目录中放置一个名为 index.php 的文件,其中包含:
<html> <head></head> <body> <script type="text/javascript"> function check() alert("hello"); </script> <iframe id="sidebnrId" name="sidebnr" src="PATH-ON-SERVER-1/iframeContent/" frameborder="0" scrolling="no"></iframe> </script> </body> </html>
这只是父窗口的内容。请注意,iFrame 内容位于另一台服务器上(因为在 SERVER 1 上)。
E.使用网络浏览器访问“PATH-ON-SERVER-2/iframeTesting_without-htaccess/” -> 没有任何反应:iframe 无法访问其父级的功能。
这是解决问题的方法
F。在 SERVER 2 上创建另一个名为“iframeTesting_with-htaccess/”的目录。
G.在该目录中放置一个名为 index.php 的文件,其中包含:
<html> <head></head> <body> <script type="text/javascript"> function check() alert("hello"); </script> <iframe id="sidebnrId" name="sidebnr" src="content-iframe/" frameborder="0" scrolling="no"></iframe> </script> </body> </html>
这一次 iFrame 不再直接指向 SERVER 1 上的内容,而是指向位于同一服务器 (SERVER 2) 上的中间虚构目录“content-iframe/”。
H.在该目录中放置一个 .htaccess 文件,其中包含:
Options +FollowSymLinks RewriteEngine On RewriteBase / RewriteRule ^content-iframe/$ PATH-ON-SERVER-1/iframeContent/ [R,NC,P]
该文件的作用是将对虚构目录的任何访问重定向到 SERVER 1 上的内容。
我。再试一次,使用网络浏览器访问“PATH-ON-SERVER-2/iframeTesting_with-htaccess/”。这次它会起作用。我希望它有所帮助:-)
【讨论】:
【参考方案4】:在现代浏览器中,您可以使用window.postMessage()
在不同域上的协作框架之间进行通信。您不能直接调用函数,但可以在两者之间传递数据或消息。见description on MDN。
【讨论】:
以上是关于允许子 iframe 从不同域调用其父窗口上的函数的主要内容,如果未能解决你的问题,请参考以下文章
什么 CSP 子 iframe 从其父 iframe 继承?