同源策略会限制 窗口(window) 和 frame 之间的通信,因此首先要知道同源策略。
同源策略目的是保护用户信息免遭信息盗窃:加入小王有两个打开的页面:一个是 shop.com,一个是 email.com。小王不希望 shop.com 的脚本可以读取 mail 的邮件,这时同源策略就起作用了。
如果两个 URL 具有相同的协议,域,和端口,则称它们是的。
以下几个URL是同源的:
- site.com
- site.com/
- site.com/a/index.htm…
以下是不同源的:
- https://site.com
- http://bbs.site.com
- site.com:8080
- http://site.org
同源策略规定:
- 如果我们有对另一个窗口的引用(window.open || iframe),并且该窗口是同源的,那么我们就具有对该窗口的全部访问权限。见代码:2-1 、2-2
- 如果不是同源的,我们就不能访问窗口中的内容:变量,文档,任何东西。唯一例外是location:我们可以修改它,使用它进行重定向。但是我们无法读取 location 。因此,我们无法看到用户当前所处的位置,也就不会泄露任何信息。
iframe 标签承载了一个单独的嵌入的窗口,它有自己的 document 和 window
iframe.contentWindow 来获取 中的 window
iframe.contentDocument 来获取 中的 document , 是 iframe.contentWindow.document 的简写。
当我们访问嵌入的窗口中的东西时,浏览器会检查 iframe 是否具有相同的源。如果不是,则会拒绝访问(对 进行写入是一个例外,它是会被允许的)。
代码 2-1 : (在 同源 情况下)
vs
事件(在 标签上)与 (在嵌入的 window 对象上)基本相同。当嵌入的窗口的所有资源都完全加载完毕时触发。
……但是,我们无法使用 访问不同源的 iframe。因此,请使用 。
但是,如果窗口的二级域相同,例如 , 和 (它们共同的二级域是 ),我们可以使浏览器忽略该差异,使得它们可以被作为“同源”的来对待,以便进行跨窗口通信。
为了做到这一点,每个这样的窗口都应该执行下面这行代码:
这样就可以了。现在它们可以无限制地进行交互了。但是再强调一遍,这仅适用于具有相同二级域的页面。
已弃用,但仍有效
属性正在被从 规范 中删除。跨窗口通信(下面将很快解释到)是建议的替代方案。
也就是说,到目前为止,所有浏览器都支持它。并且未来也将继续支持它,而不会导致使用了 的旧代码出现问题。
代码 2-1 : (在 不同源 情况下)注意端口
当一个 iframe 来自同一个源时,我们可能会访问其 ,但是这里有一个陷阱。它与跨源无关,但你一定要知道。在创建 iframe 后,iframe 会立即就拥有了一个文档。但是该文档不同于加载到其中的文档!
因此,如果我们要立即对文档进行操作,就可能出问题,因为那是错误的文档。
正确的文档在 触发时肯定就位了。但是,只有在整个 iframe 和它所有资源都加载完成时, 才会触发。
看一下下面这段代码:
获取 的 window 对象的另一个方式是从命名集合 中获取:
- 通过索引获取: —— 文档中的第一个 iframe 的 window 对象。
- 通过名称获取: —— 获取 的 iframe 的 window 对象。
例如:
一个 iframe 内可能嵌套了其他的 iframe。相应的 对象会形成一个层次结构(hierarchy)。
可以通过以下方式获取:
- —— “子”窗口的集合(用于嵌套的 iframe)。
- —— 对“父”(外部)窗口的引用。
- —— 对最顶级父窗口的引用。
例如:
我们可以使用 属性来检查当前的文档是否是在 iframe 内打开的:
特性(attribute)允许在 中禁止某些特定行为,以防止其执行不被信任的代码。它通过将 iframe 视为非同源的,或者应用其他限制来实现 iframe 的“沙盒化”。
对于 ,有一个应用于其上的默认的限制集。但是,我们可以通过提供一个以空格分隔的限制列表作为特性的值,来放宽这些限制,该列表中的各项为不应该应用于这个 iframe 的限制,例如:。
换句话说,一个空的 特性会施加最严格的限制,但是我们用一个以空格分隔的列表,列出要移除的限制。
以下是限制的列表:
-
默认情况下, 会为 iframe 强制实施“不同来源”的策略。换句话说,它使浏览器将 视为来自另一个源,即使其 指向的是同一个网站也是如此。具有所有隐含的脚本限制。此选项会移除这些限制。
-
允许 更改 。
-
允许在 中提交表单。
-
允许在 中运行脚本。
-
允许在 中使用 打开弹窗。
查看 官方手册 获取更多内容。
接口允许窗口之间相互通信,无论它们来自什么源。
因此,这是解决“同源”策略的方式之一。它允许来自于 的窗口与来自于 的窗口进行通信,并交换信息,但前提是它们双方必须均同意并调用相应的 JavaScript 函数。这可以保护用户的安全。
这个接口有两个部分。
1 postMessage
想要发送消息的窗口需要调用接收窗口的 方法。换句话说,如果我们想把消息发送给 ,我们应该调用 。
参数
要发送的数据。可以是任何对象,数据会被通过使用“结构化序列化算法(structured serialization algorithm)”进行克隆。IE 浏览器只支持字符串,因此我们需要对复杂的对象调用 方法进行处理,以支持该浏览器。
指定目标窗口的源,以便只有来自给定的源的窗口才能获得该消息。
2 onmessage
为了接收消息,目标窗口应该在 事件上有一个处理程序。当 被调用时触发该事件(并且 检查成功)。
event 对象具有特殊属性:
- 从 传递来的数据。
- 发送方的源,例如 。
- 对发送方窗口的引用。如果我们想,我们可以立即 回去。
要为 事件分配处理程序,我们应该使用 ,简短的语法 不起作用。
第一次渲染输出: ,
刷新页面输出: ,
我们可以得出以下结论:
- iframe 嵌套的 2.html 设置的 cookie 我们可以从 1.html 中获取
- iframe 中设置的 cookie 会覆盖 1.html cookie 中 Name 相同的值( 不同源也是同样的效果 )
补充:
同域才能访问父/祖父/组祖父/... 页面的方法
前提:1.html iframe 引用 2.html , 2.html iframe 引用 3.html 见下图,注意3个页面的端口
结论: 当 1.html 和 2.html 跨域,1.html 和 3.html不跨域时,3.html 可以通过 访问 1.html 的方法。 见下图:

跨域也能获取并覆盖 父/祖父/组祖父/... 页面的 cookie
结论:iframe 嵌套,每层都互相跨域的页面,最内层的依然可以访问最外层的 cookie。见下图
之前对 cookie 认识不够全面, cookie 也受 domain 的影响。如果cookie 的 domain不一致则不能互相访问、修改;(设置domain解决跨域的原理)

版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/15621.html