Chrome 禁止修改 document.domain

如果您的网站依赖于设置 document.domain,则需要采取相应行动。

毛德·纳尔帕斯
Maud Nalpas
Eiji Kitamura
北村英二

具体变化以及原因

Chrome 115 开始,网站将无法设置 document.domain:Chrome 会使 document.domain 不可变。如需进行跨域通信,您需要使用替代方法,例如 postMessage() 或 Channel Messaging API。

请注意,这项变更将逐步推出。

我们希望其他浏览器最终会弃用并移除此功能。如需了解详情,请查看浏览器兼容性部分。

为什么要使 document.domain 不可变?

document.domain 旨在获取或设置源站的主机名。许多网站都会设置 document.domain,以允许在同一网站但跨源的网页之间进行通信。

虽然这是一种便捷的方法,但它会放宽同源政策,因而会带来安全风险。围绕 document.domain 的安全问题导致规范发生变化,警告用户应避免使用它

详细说明:为什么要使 document.domain 不可变?

document.domain的使用情况

许多网站将 document.domain 设置为允许在同一网站但跨源网页之间进行通信。

同网站但跨源网站具有相同的 eTLD+1,但两者的子网域不同。

截至目前,document.domain 的使用方式如下:

假设 https://parent.example.com 上的某个页面嵌入了 https://video.example.com 中的 iframe 页面。这些网页具有相同的 eTLD+1 (example.com),但存在不同的子网域。如果两个网页的 document.domain 均设置为 'example.com',浏览器会将这两个来源视为同一来源。

https://parent.example.com 设置 document.domain

// Confirm the current origin of "parent.example.com"
console.log(document.domain);

// Set the document.domain
document.domain = 'example.com';
console.log(document.domain);

https://video.example.com 设置 document.domain

// Confirm the current origin of "video.example.com"
console.log(document.domain);

// Set the document.domain
document.domain = 'example.com';
console.log(document.domain);

现在,您可以在 https://parent.example.com 上针对 https://video.example.com 创建跨源 DOM 操作。

网站设置 document.domain 是为了便于同网站文档的通信更轻松。由于这项更改放宽了同源政策,因此父页面能够访问 iframe 的文档并遍历 DOM 树,反之亦然。

这是一种便捷的方法,但会带来安全风险。

document.domain 的安全问题

围绕 document.domain 的安全问题导致警告用户应避免使用的规范发生变化。

例如,当两个页面设置 document.domain 时,它们可以假装它们是同源。当这些网页使用包含不同子网域的共享托管服务时,这一点尤为重要。设置 document.domain 后,用户就可以访问由同一服务托管的所有其他网站,让攻击者可以更轻松地访问您的网站。之所以能够这么做,是因为 document.domain 会忽略网域的端口号部分。

如需详细了解设置 document.domain 的安全隐患,请参阅 MDN 上的“Document.domain”页面

浏览器兼容性

如何知道自己的网站是否受到影响?

如果您的网站受此变更的影响,Chrome 会在开发者工具的“Issues”面板中向您发出警告 - 此警告已于 2022 年添加。请注意开发者工具右上角的黄色标志。

开发者工具中问题警告的屏幕截图

您还可以通过 LightHouse 已弃用 API 审核运行您的网站,找出所有计划从 Chrome 中移除的 API。

如果您已设置 Reporting API,Chrome 会向您发送弃用报告,向您通知即将弃用的这一功能。详细了解如何将 Reporting API 与现有报告收集服务搭配使用,或构建您自己的内部解决方案。

如何查看这一变更的实际应用?

Chrome 115 开始,这项变更将逐步推出。 如果这项变更尚未在 Chrome 浏览器中推出,若要查看其实际效果,您可以按照以下方法启用:

  1. 打开“chrome://flags/#origin-agent-cluster-default
  2. 选择启用
  3. 重启 Chrome。

我可以使用哪些替代方案?

最好是完全不要修改 document.domain,例如通过在同一来源上托管网页和所有组成框架。这适用于所有浏览器的所有版本。但是,这可能需要对应用进行大量重新工作,因此还值得研究一下继续支持跨源访问的替代方案。

使用 postMessage() 或 Channel Messaging API,而不要使用 document.domain

在大多数用例中,跨源 postMessage()Channel Messaging API 可以替换 document.domain

在以下示例中:

  1. https://parent.example.com 通过 postMessage() 发送消息,在 iframe 中请求 https://video.example.com 来操控 DOM。
  2. https://video.example.com 在收到该消息后会立即对 DOM 执行操作,并将操作成功通知给父级。
  3. https://parent.example.com 确认操作成功。

https://parent.example.com 上:

// Send a message to https://video.example.com
iframe.postMessage('Request DOM manipulation', 'https://video.example.com');

// Receive messages
iframe.addEventListener('message', (event) => {
  // Reject all messages except ones from https://video.example.com
  if (event.origin !== 'https://video.example.com') return;

  // Filter success messages
  if (event.data === 'succeeded') {
    // DOM manipulation is succeeded
  }
});

https://video.example.com 上:

// Receive messages
window.addEventListener('message', (event) => {
  // Reject all messages except ones from https://parent.example.com
  if (event.origin !== 'https://parent.example.com') return;

  // Do a DOM manipulation on https://video.example.com.

  // Send a success message to https://parent.example.com
  event.source.postMessage('succeeded', event.origin);
});

试用一下,看看它是如何工作的。如果您有不适用于 postMessage() 或 Channel Messaging API 的特定要求,请通过 @ChromiumDev 在 Twitter 上告诉我们,或者在 Stack Overflow 上使用 document.domain 标记提问。

作为最后的补救手段,请发送 Origin-Agent-Cluster: ?0 标头

如果您有充分的理由继续设置 document.domain,可以将 Origin-Agent-Cluster: ?0 响应标头随目标文档一起发送。

Origin-Agent-Cluster: ?0

Origin-Agent-Cluster 标头会指示浏览器是否应由以源为键的代理集群处理文档。如需详细了解 Origin-Agent-Cluster,请参阅使用 Origin-Agent-Cluster 标头请求性能隔离

发送此标头时,您的文档可以继续设置 document.domain,即使它默认变得不可变也是如此。

需要该行为的所有其他文档也需要发送 Origin-Agent-Cluster(请注意,如果只有一个文档设置了 document.domain,则无效)。

为企业政策配置“OriginAgentClusterDefaultEnabled

或者,您的管理员可以将 OriginAgentClusterDefaultEnabled 政策配置为 false,从而在组织中的 Chrome 实例上默认将 document.domain 设置为可设置。有关详情,请参阅 Chrome 企业版政策列表和管理 | 文档

资源

致谢

照片由 Finan Akbar 提供,由 Unsplash 提供