代码之家  ›  专栏  ›  技术社区  ›  Dan Lew

为什么帧断路器跨域工作,并且可以有条件地使用帧断路器?

  •  10
  • Dan Lew  · 技术社区  · 17 年前

    我一直在调查 frame breaking 最近出现了一些与 same origins policy 我很难理解。

    假设我在域A上有一个page breaker.html,在域B上有一个page container.html,那么这个示例的frame breaker代码将进入breaker.html,如下所示:

    if (top !== self) top.location.href = self.location.href;
    

    这将成功地将breaker.html从container.html中分离出来,但我不明白为什么应该这样做。从我对同宗政策的解读来看, top.location 不应该接近 完全 ,因为container.html与breaker.html位于不同的域中。更奇怪的是,上面的位置。 只写 :

    // Fails if Container.html is on a different domain than Breaker.html
    alert(top.location);
    

    这对我来说是有问题的,因为我正在尝试编写代码,允许我的页面位于iframe中,但前提是它与其父页面位于同一域中(或位于配置的允许域中)。然而,这似乎是不可能确定的,因为相同的起源政策拒绝我访问父母的位置。

    所以我有两个问题,基本上:

    1. 为什么上面的框架断路器代码可以工作?

    2. 有没有办法有条件地打破框架,或者唯一能做的就是 top !== self 是吗?(特别是,我希望能够读取域,这样我就可以提供一个允许的域列表;仅仅检查我是否在同一个域中是不理想的。)

    3 回复  |  直到 11 年前
        1
  •  1
  •   Brian    17 年前

    对于数字1的答案:在安全性方面,读访问和写访问之间有很大的区别。能够读取top.location.href是一个安全问题。能够 to top.location.href不是。

    至于你的问题的答案,我对javascript的了解还不足以确定,但有一个想法是假设如果读取top.location失败(检查异常),它就在另一个域中。

        2
  •  0
  •   Adam Nelson    17 年前

    问题1的答案是,出于遗留原因,可以对top.location.href使用相等运算符。breaker.html无法读取top.location.href,但可以将其与其他值进行比较。

    问题2的答案变为“否”,您必须使用!=to part,因为您将无法从cross-domain breaker.html在top.location.href上执行子字符串。

    我可能错了,但这是我对当前iFrame世界的理解。

        3
  •  0
  •   i β    11 年前

    这是针对问题2的问题:如果您想获取parent.location(而不是top.location)的href,可以执行以下操作:

    if ((window.top === window.parent) && (history.length==1)) parentHREF=document.referrer;
    

    基本上,此代码的作用是:
    〔1〕 检查父框架是否为顶部框架,因为即使父框架不是顶部框架,也只能获取父框架的Href。
    〔2〕 在加载其源之前检查iframe的历史记录是否为空,因为如果不是…document.referer将返回此帧历史记录中的最后一个href。

    之后,您会遇到一个新问题:在case history.length的值不止一个的情况下,您可以使用主机名的白名单来检查是否必须打开它:

    if ([location.hostname, 'stackoverflow.com'].indexOf(location.hostname)>=0) hasToBeOpened=true;
    

    请注意,另一个选项:可以使用登录页检查“第一”页是否必须打开,请使用以下代码:

    <head>
    <script>
    var parentHREF;
    if ((window.top === window.parent) && (history.length==1)) parentHREF=document.referrer;
    if (/*conditions mentiones above*/) document.write("<META http-equiv='refresh' content='0;URL=http://example.com/go-here.html'>");
    </script>
    </head>
    

    这样,“第一”页将替换历史记录的第一个(在本例中是第一个)值。这段代码是“example.com”是您的域。

    推荐文章