JavaScript document.domain 未捕获的 DOMException:阻止了具有来源的帧

JavaScript document.domain Uncaught DOMException: Blocked a frame with origin

当我测试 SOP 时,我遇到了这种情况,两个文档与我预期的相同域有关系,当我尝试获取位置时它会抛出错误。

重现问题:

  1. 打开https://www.google.com
  2. 从控制台let opened = window.open("https://www.google.com")
  3. 从同一个 window 做 opened.location.toString() 这将 return 正确的位置
  4. 从第二个选项卡的控制台执行 document.domain = "www.google.com"
  5. 从第一个选项卡执行 opened.location.toString(),您将得到一个错误

    Uncaught DOMException: Blocked a frame with origin "https://www.google.com" from accessing a cross-origin frame.
    at <anonymous>:1:12
    

谁能解释一下这种奇怪的行为?

首先,我建议您阅读Same-origin Policy

The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.

Two URLs have the same origin if the protocol, port (if specified), and host are the same for both. You may see this referenced as the "scheme/host/port tuple", or just "tuple". (A "tuple" is a set of items that together comprise a whole — a generic form for double/triple/quadruple/quintuple/etc.)

在这种特殊情况下,您使用 HTTPS 协议打开 window,但是当您设置域时,协议更改为HTTP,见下图:

按照1,如果协议不一样,那就违反了原则,所以会报错

Uncaught DOMException: Blocked a frame with origin "https://www.google.com" from accessing a cross-origin frame.

cross-origin 是这里的关键字。

此外,请查看此 SecurityError: Blocked a frame with origin from accessing a cross-origin frame 了解更多详情。

这个错误不是错误。同源策略是一种安全机制,确保 window 对象只能访问它们被授权获取的信息。在您的情况下,这包括访问 opened.location.

创建时,两个选项卡具有相同的来源,这允许第一个选项卡访问 opened.location。但是在调用 document.domain='www.google.com' 之后,它们不再存在了。

"What? But in both tabs, window.location.origin are identical"

是的,但有点复杂。原点由 scheme/host/port 元组定义,有关详细信息,请参阅@TheUnknown 的回答。 scheme 和 host 始终保持不变,它们是 window.location.origin.

字符串中包含的那个

需要知道的棘手的事情是,对 document.domain 的任何调用,包括 document.domain = document.domain,都会导致端口号被 null[=36= 覆盖],因此导致两个选项卡的来源不同,并阻止它们相互传达 opened.location 等信息,从而导致错误。

从 MDN 中提取的信息 guide on same-origin policy

这将有点无意义(只是陈述事实),不过:

  • 在windowB中更改domain后,windowB停止将windowA计入opener

  • 由于windowA不再被认为是windowB的开启者,因此禁止访问。

这让我觉得,改变 document.domain 被认为是潜在的不安全的,并且 "punished" 通过孤立 child window。