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

Javascript 为什么断帧器可以跨域工作,并且可以有条件地使用断帧器?,javascript,iframe,same-origin-policy,Javascript,Iframe,Same Origin 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中分离出来,但我不明白为什么应该这样做。从我对

我最近一直在研究代码,遇到了一些与代码相关的非常奇怪的行为,我很难理解这些行为

假设我在域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位于不同的域中。更奇怪的是,似乎top.location只写

// Fails if Container.html is on a different domain than Breaker.html
alert(top.location);
这对我来说是个问题,因为我正在尝试编写代码,允许我的页面位于iframe中,但前提是它与其父页面位于同一个域中(或者位于已配置的允许域中)。但是,似乎无法确定这一点,因为同一来源策略拒绝我访问父位置

我有两个问题,基本上:

  • 为什么上面的断帧代码可以工作

  • 有没有办法有条件地中断帧,或者唯一可以做的检查是
    top!==自我
    ?(特别是,我希望能够读取域,以便提供允许的域列表;简单地检查我是否在同一个域中并不理想。)


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


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

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

    问题2的答案变成“否”,您必须使用!==因为您将无法从跨域breaker.html在top.location.href上执行子字符串,所以无法分离


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

    这是问题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>
    
    
    var-parentHREF;
    如果((window.top==window.parent)&&(history.length==1))parentHREF=document.referer;
    如果(/*条件提及上述*/)文件,请填写(“”);
    

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

    “同源策略防止从一个源加载的文档或脚本从另一个源获取或设置文档的属性。”-这就是我挂断电话的地方。此外,我还考虑过做#2,但我还想让管理员指定可以在哪些域中设置框架-我将改写问题。写入top.location.href不会设置外来文档的任何属性;相反,它卸载以前的文档,并在其位置加载新文档。@Daniel:我对差异的评论是从实用的角度出发的,而不是从技术规范的角度出发的。我的观点是,这不是一个合法的安全问题,因此是合法的,而不是暗示规范说这是可以的。