当我测试SOP时,我遇到这种情况,两个文档与我期望的域具有相同的关系,并且当我尝试获取位置时会引发错误。
重现该问题:
let opened = window.open("https://www.google.com")
opened.location.toString()
,它将返回正确的位置document.domain = "www.google.com"
在第一个标签中执行opened.location.toString()
,您会收到错误消息
Uncaught DOMException: Blocked a frame with origin "https://www.google.com" from accessing a cross-origin frame.
at <anonymous>:1:12
有人可以解释这种奇怪的行为吗?
答案 0 :(得分:3)
首先,我建议您阅读Same-origin Policy。
同源策略是一种严格的安全机制,它限制了 从一个来源加载的文档或脚本如何与一个 来自另一个来源的资源。它有助于隔离潜在的恶意软件 文档,减少可能的攻击媒介。
如果协议,端口(如果指定)和主机都相同,则两个URL的来源相同。您可能会看到这被称为“方案/主机/端口元组”,或仅称为“元组”。 (“元组”是一起组成一个整体的一组项目-双重/三元组/四元组/五元组/等的通用形式。)
在这种情况下,您使用 HTTPS 协议打开一个窗口,但是在设置域时,该协议会更改为 HTTP < / em> ,请参见下图:
根据1,如果协议不同,则违反了原理,因此会出现错误
未捕获的DOMException:阻止了具有来源的帧 通过访问跨域框架获得“ https://www.google.com”。
跨域是此处的关键字。
另外,请查看此SecurityError: Blocked a frame with origin from accessing a cross-origin frame以获得更多详细信息。
答案 1 :(得分:3)
此错误不是错误。同源策略是一种安全机制,可确保窗口对象仅有权访问他们被授权获取的信息。就您而言,这包括可以访问opened.location
。
创建时,两个选项卡都具有相同的来源,这使第一个选项卡可以访问opened.location
。但是在致电document.domain='www.google.com'
之后,他们不再了。
“什么?但是在两个标签中,window.location.origin
都是相同的”
是的,但是有点复杂。原点由scheme / host / port元组定义,有关更多详细信息,请参见@TheUnknown的答案。方案和主机始终保持不变,它们是window.location.origin
字符串中包含的那个。
要知道的一件棘手的事情是,对document.domain
的任何调用(包括document.domain = document.domain
)都会导致端口号被null
覆盖,从而导致这两个标签的来源有所不同,并阻止了它们之间相互传达诸如opened.location
之类的信息,从而导致错误。
从MDN的guide on same-origin policy中提取的信息
答案 2 :(得分:0)
尽管如此,这还是有些信息(只是陈述事实)
在窗口B中更改domain
之后,窗口B停止将窗口A记为opener
。
由于不再将窗口A视为窗口B的打开器,因此禁止访问。
这让我认为,更改document.domain
可能被认为是不安全的,并且通过孤立子窗口来“惩罚”。