当我测试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
谁能解释这种奇怪的行为?
这个错误不是错误。同源策略是一种安全机制,可确保窗口对象只能访问它们有权获取的信息。在您的情况下,这包括访问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中提取的信息
首先,我建议你阅读Same-origin Policy。
同源策略是一种关键的安全机制,它限制从一个源加载的文档或脚本如何与来自另一个源的资源交互。它有助于隔离潜在的恶意文档,减少可能的攻击媒介。
如果协议,端口(如果指定)和主机两者都相同,则两个URL具有相同的来源。您可能会将此引用称为“scheme / host / port tuple”,或仅仅是“元组”。 (“元组”是一组共同构成整体的项目 - 双/三/四/五元组的通用形式。)
在这种特殊情况下,您使用HTTPS协议打开一个窗口,但是当您设置域时,协议将更改为HTTP,请参见下图:
根据1,如果协议不一样,那么它违反了原则,因此你得到了错误
未捕获的DOMException:阻止具有原始“https://www.google.com”的帧访问跨源帧。
cross-origin是这里的关键字。
另外,请查看此SecurityError: Blocked a frame with origin from accessing a cross-origin frame了解更多详情。
尽管如此,这将有点无法提供信息(只是陈述事实):
domain
后,窗口B将会计窗口A停止为opener
。这让我想到,改变document.domain
被认为是潜在的不安全因素并且通过孤儿子窗口而受到“惩罚”。