Chrome 将禁止修改 document.domain

2,798 阅读5分钟

警告

正如我们在 2022年1月份宣布的,我们将在 Chrome 115 中弃用 document.domain 设置器。如果您的网站依赖于通过 document.domain 来放宽 同源策略,您需要立即采取行动。

继续阅读了解为什么会有这个改变,或者跳到你可以实施的 备选方案

#发生了什么,以及为什么?

从 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

// 确认 "parent.example.com" 的当前来源
console.log(document.domain);

// 设置 document.domain
document.domain = 'example.com';
console.log(document.domain);

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

// 确认 "video.example.com" 的当前来源
console.log(document.domain);

// 设置 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 会在 DevTools Issues 面板中发出警告 - 这个警告已经在 2022 年加入了。

请注意 DevTools 右上角的黄色标志。

image.png

您还可以通过 LightHouse 弃用 API 审核 运行您的网站,以查找所有预定从 Chrome 中删除的 API。

如果您已设置报告 API,则 Chrome 已向您发送了弃用报告,以通知您即将弃用。了解有关如何使用报告 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 在 iframe 中请求 https://video.example.com 以通过 postMessage() 发送消息来操作 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,请通过 Twitter via @ChromiumDev 或在 Stack Overflow 上使用 document.domain tag 来让我们知道。

#作为最后的选择,通过发送 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 企业政策列表和管理 | 文档

#资源

#鸣谢

Photo by Finan Akbar on Unsplash