如何在帧之间进行通信?

时间:2010-04-02 23:56:38

标签: html frames html-frames

我正在维护一个类似这样的应用程序:

页面A带有显示页面B的框架。现在,页面B是单独域中完全不同产品的一部分。

现在,他们想要在单击B中的选项时,将WHOLE页面重定向到A中的另一个页面。问题是A的URL类似www.client.A.com/Order/Details/123,当我们单击时它应该重定向到像www.client.A.com/Order/Edit/123这样的东西,但是B对A不知道。它不知道当前选择了哪个顺序#或者有关A的任何东西。具有框架B的人确实知道它。

现在我的解决方案是重定向到AllOrders,所以像client.MyCompany / Orders

但由于B不知道哪个client正在调用它(它是一个多租户应用),我会在webconfig中添加它。 (因此每个客户端都有自己的webconfig,其值不同)。

我没有找到最佳解决方案,但我想不出别的什么!我已经尝试将页面A中所需的URL放在隐藏的Div中(因为A确实知道所有信息),然后尝试从B读取整个页面的DOM以找到它....不幸的是我只能访问帧B的DOM ...(我试过jquery)。

我知道框架是邪恶的,但这就是它的写法...任何想法?

谢谢!

3 个答案:

答案 0 :(得分:25)

如果父页面A和iframe页面B位于不同的域中,您将无法通过B的父属性访问方法或字段,A中的脚本也无法访问B的内容,也不会能够在A和B之间共享全局变量。页面A和页面B之间的这个边界是浏览器安全模型的关键部分。这就是通过阅读银行网页的javascript的内部变量来阻止evil.com包装您的在线银行网页并窃取您的帐户信息。

如果您需要最新一代浏览器,可以使用此处其中一个答案中提到的postmessage技术。如果您需要支持旧版浏览器,则可以使用浏览器中的跨域客户端脚本技术传递少量信息。这方面的一个例子是使用iframe在外部页面A和内部页面B之间传递信息。这并不容易,并且涉及许多步骤,但它可以完成。我前一段时间写了一篇article

您将无法监控来自父网页A的B的iframe中的点击次数。这违反了多个级别的浏览器安全政策。 (点击劫持,换一个)你将无法看到B的URL何时发生变化 - A可以写入iframe.src属性来更改URL,但是一旦iframe.src指向与A的域不同的域,A无法再读取iframe.src属性。

如果A和B位于同一根域的不同子域中,您可能有机会将域“降低”到公共根。例如,如果外部页面A托管在子域A.foo.bar.com中,而B托管在子域foo.bar.com中,那么您可以将页面A中的域名降低到foo.bar.com(通过分配在A的脚本中window.domain =“foo.bar.com”)。然后,页面A将表现为页面B的对等体,然后两者可以根据需要访问彼此的数据,即使A在技术上是从不同于B的域提供的。我也在domain lowering上写了一篇文章。

域名降低只能剥离最内层子域以在根域的上下文中运行。您无法将A.foo.bar.com更改为abc.com。

将域降低到公共根域也存在轻微风险。当您在自己的子域中操作页面时,您的html和脚本将与公共根域之外的其他子域隔离。如果某个其他子域中的服务器遭到入侵,则它不会真正影响您的html页面。

如果将页面的域降低到公共根域,则会将内部公开给在公共根域上运行的脚本,以及从已将域降低到公共根的其他子域的脚本。如果某个其他子域中的服务器遭到入侵,它将可以访问您脚本的内部,因此它也可能已经破坏了您的子域。

答案 1 :(得分:7)

如果页面&框架不在同一个域上,您必须使用postmessage,因为安全问题,同域策略禁止不同域的页面/帧之间的正常javascript通信。

postmessage是html5和works in all modern browsers (including IE8)的一部分。如果你需要支持旧的浏览器(特别是IE6 / 7),你可以使用jQuery postmessage plugin(对于旧版浏览器来说,它会透明地回归到一些不错的哈希标记技巧)。

并且作为旁注:不确定框架是否是邪恶的,有一些与它们相关的问题(可用性,搜索引擎优化等),但我做了一些研究并且我认为most of these can be tackled

答案 2 :(得分:2)

如果你想在javascript中的帧之间进行通信,你可以使用'parent':

如果帧A具有变量值,例如:

var orderNo = 2;

对于帧B来读它,它将引用

var frameA_orderNo = parent.frames[0].orderNo;

(假设帧A是声明的第一帧)

因此,您可以在每个框架中设置另一个框架可以读取的全局变量,因此您可以在旧式javascript中获取订单#(从未在jquery中尝试过)。

哇帧 - 从未想过我会再次想到它们。