为什么断路器跨域工作,您是否可以有条件地使用断路器?

时间:2009-06-04 18:17:36

标签: javascript iframe same-origin-policy

我最近一直在调查frame breaking代码,并且遇到了一些与我无法理解的same origins policy相关的奇怪行为。

假设我在域A上有一个Breaker.html页面,在域B上有一个页面Container.html。示例帧断路器代码将进入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中的代码,但前提是它与其父级位于同一个域中(或者位于配置的允许域中)。但是,似乎无法确定这一点,因为相同的起源政策拒绝我访问父母的位置。

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

  1. 为什么上述断帧器代码完全有效?

  2. 有没有办法有条件地破坏帧,或者唯一可以检查的是top !== self? (特别是,我希望能够阅读域名,以便我可以提供允许域名列表;只是检查我是否在同一个域中是不理想的。)

3 个答案:

答案 0 :(得分:1)

对第1号的回答:在安全性方面,读访问和写访问之间存在很大差异。能够读取top.location.href是一个安全问题。能够到top.location.href不是。

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

答案 1 :(得分:0)

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

问题2的答案变为否定,你必须使用!==分开,因为你将无法在跨域breaker.html的top.location.href上执行子字符串。

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

答案 2 :(得分:0)

这是针对问题2:如果你想获取parent.location的HREF(而不是top.location),你可以这样做:

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

基本上这个代码的作用是:
[1] 检查父框架是否是最顶层框架,因为即使它不是顶部框架,也只能采用父框架的HREF。 /> [2] 在加载源之前检查iframe的历史记录是否为空,因为如果不是... document.referrer将返回此帧历史记录中的最后一个HREF。

之后,您遇到了一个新问题:如果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”是您的域名。