【问题标题】:Why can't an iframe set its parent's location.hash?为什么 iframe 不能设置其父级的 location.hash?
【发布时间】:2009-06-15 23:46:25
【问题描述】:

我有一个包含 iframe 的窗口,包含 iframe,如下所示:

+---------------+
|      Top      |
| +-----------+ |
| |   Middle  | |
| | +-------+ | |
| | | Inner | | |
| | +-------+ | |
| +-----------+ |
+---------------+

Top 和 Middle 在同一个域中,但 Inner 在不同的域中。我需要 Inner 与 Top 沟通。我知道在 IE7 中支持(我需要支持)的唯一方法是更改​​窗口位置的哈希值。但是,我不希望位置栏中的信息闪烁,所以我引入了中间 iframe。

我希望 Inner 更改 Middle 的哈希值。 Middle 将读取其哈希值并通知 Top,它有权直接与之交谈。

但是,在 Firefox 3 中,我无法从 Inner 写入 Middle 的哈希值。没有引发错误,但哈希看起来没有变化。写入其location.href 会引发权限错误。

Top 可以写 Middle 的 hash,但是 Middle 可以写 Inner 的 hash,Top 可以写 Inner 的 hash,Inner 和 Middle 都可以写 Top 的 hash,所以 只有有序对 那行不通的就是我想要的! (我已经为此工作了一段时间。)

我已经在一个最小的测试用例中重现了这一点。起初,我为同一个域的所有三个页面提供服务。当我将 Inner 放在不同的域上时,我得到了有问题的行为。当我把 Middle 放在第二个域上时,每个人都可以再次给每个人写信。

为什么 Inner 不能写入 Middle 的哈希?


附录:由于同源政策,许多人认为这不应该是可能的。这正是我试图绕过的政策。这种确切的情况——设置(但不读取)另一个窗口的位置——应该可以跨域进行。我还没有找到这种效果的浏览器文档,但是我找到了很多文章和演示。这本质上是 HTML 5 的 postMessage() 的前身。

参考:http://softwareas.com/cross-domain-communication-with-iframes

【问题讨论】:

  • 听起来可能是安全问题。
  • 在 SO 上有一个关于这个问题的问题——Bugzilla 中的一个错误。
  • @Eric:很高兴知道。你有那些链接吗?将它们发布为答案,我会接受。

标签: javascript firefox iframe security


【解决方案1】:

父框架可以使用以下方法设置子框架的“src”属性(此处使用 jquery):

$("#iframeWindow").attr('src', "http://<CHILD URL>/#hello");

子 iframe 可以使用以下方法设置父窗口的 href(地址栏内容):

window.top.location.href = "http://<PARENT URL>/#hello"

在父母和/或孩子中,您需要轮询更改,

var last = "";
setInterval(function() {
    if(last == window.location.href) return;
    last = window.location.href;

    //do stuff with 'window.location.hash'
}, 1000);

注意,如果可以的话就更好了

window.top.location.href = window.top.location.href + "#hello"

但不允许读取位置对象(href 和哈希)

于 11 月 3 日在 chrome、ie6/7/9、firefox 3.6/4 上测试

edit1:如果人们愿意,可以进行演示

edit2:http://dl.dropboxusercontent.com/u/14376395/html/xdomain.html :)

edit3:当心:如果您使用此方法,请确保您可以控制所有 iframe 页面,否则恶意的第三方网站可能会使用哈希标签控制您的页面

edit4:Google JavaScript API 目前正在使用更好的解决方案http://ternarylabs.com/2011/03/27/secure-cross-domain-iframe-communication/

edit5:保管箱域名更改为“dl.dropboxusercontent.com”

【讨论】:

  • 已添加(我使用 dropbox/jsfiddle 作为两个域)
  • 为了解决 iframe 中不允许 window.top.location.href = window.top.location.href + "#hello" 的问题,父窗口可以传入自己的 url(当然是 urlencoded)作为它发送给子窗口的哈希消息的一部分。
【解决方案2】:

要能够设置 location.hash,您必须首先获取位置。同源策略禁止您获取位置。

【讨论】:

  • 同源策略实际上并不会阻止您获取 Location 对象,只会阻止它的属性。你应该仍然可以设置它们;请参阅问题附录中的链接。
【解决方案3】:

根据 EricLaw 的说法,这听起来像是 Firefox 中的一个错误,已在 Bugzilla 中提交。

【讨论】:

    【解决方案4】:

    是否所有帧都包含具有相同原点的位置? (例如,相同的协议、相同的域、相同的端口)。如果不是,如果一个框架可以修改另一个框架,那就是一个潜在的安全漏洞——谷歌同源策略。但如果没有更多细节,很难提供更好的答案。

    【讨论】:

    • 这就是问题所在:Top和Middle同源;内有不同的起源。设置位置应该是同源策略中的一个(安全的,我假设是故意的)间隙。请参阅问题的附录。
    【解决方案5】:

    我无法回答哈希的为什么位,但你见过 John Resig 的 workpostMessage 吗?您在使用 FF3 时遇到问题,FF3 恰好是支持postMessage、宾果游戏的浏览器之一 :-)

    如果做不到这一点,还有xssinterface 库。貌似稳定,但我没有亲自尝试过。

    【讨论】:

      【解决方案6】:

      正如 Alex 所说,这是一个安全问题。如果 Inner 在不同的域上,您将无法访问顶层。这是为了避免Cross-site Scripting

      【讨论】:

      • 查看问题的附录。无论域如何,都应该允许写入该位置。
      猜你喜欢
      • 1970-01-01
      • 2023-03-30
      • 2021-05-06
      • 2011-12-24
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多