为啥分帧器可以跨域工作,可以有条件地使用分帧器吗?
Posted
技术标签:
【中文标题】为啥分帧器可以跨域工作,可以有条件地使用分帧器吗?【英文标题】:Why do frame breakers work cross-domain, and can you conditionally use frame breakers?为什么分帧器可以跨域工作,可以有条件地使用分帧器吗? 【发布时间】:2010-10-31 10:27:22 【问题描述】:我最近一直在调查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 中的代码,但前提是它与其父级位于同一域中(或位于配置的允许域中)。但是,这似乎无法确定,因为同源政策拒绝我访问父母的位置。
所以我有两个问题,基本上:
为什么上面的帧中断代码完全起作用?
有没有办法有条件地打破帧,或者唯一能做的检查是top !== self
? (特别是,我希望能够读取域,以便提供允许域的列表;简单地检查我是否在同一个域中并不理想。)
【问题讨论】:
【参考方案1】:这是针对第 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的值大于1,你可以使用主机名白名单来检查它是否必须打开:
if ([location.hostname, '***.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”是您的域。
【讨论】:
【参考方案2】:问题 1 的答案是,出于遗留原因,可以对 top.location.href 使用相等运算符。 Breaker.html 无法读取 top.location.href 但它可以将其与另一个值进行比较。
然后问题 2 的答案变为否,您必须使用 !== 来分开,因为您将无法从跨域断路器.html 中对 top.location.href 执行子字符串。
我可能是错的,但这是我对当前 iframe 世界的理解。
【讨论】:
【参考方案3】:对于第 1 点的回答:在安全性方面,读取访问权限和写入访问权限之间存在很大差异。能够读取 top.location.href 是一个安全问题。不能写入到 top.location.href。
至于您的问题的答案,我不太了解 javascript,无法确定,但一个想法是假设如果读取 top.location 失败(检查异常),它位于不同的域中。
【讨论】:
“同源策略防止从一个源加载的文档或脚本从另一个源获取或设置文档的属性。” - 这就是我挂断电话的地方。另外,我考虑过 #2,但我也希望允许管理员指定可以在哪些域中进行框架 - 我将改写问题。 写入 top.location.href 不会设置外部文档的任何属性;相反,它会卸载前一个文档并在其位置加载一个新文档。 @Daniel:我对差异的评论是出于实用的角度,而不是从技术规范的角度。我的观点是,这不是一个合法的安全问题,因此是合法的,而不是暗示规范说没问题。以上是关于为啥分帧器可以跨域工作,可以有条件地使用分帧器吗?的主要内容,如果未能解决你的问题,请参考以下文章