Chrome 115 来了,你的网站还好吗

avatar

最近项目中有出现如下的现象

回调父级方法失败 closeDialog DOMException: Blocked a frame with origin "https://xxx.test.cn" from accessing a cross-origin frame.
    at HTMLButtonElement.<anonymous> 

原因是受限于浏览器的同源策略,但又有同一站点但跨源页面之间通信的需求,于是将document.domain 的值设置为其当前域或其当前域的父域来实现同一站点但跨源页面之间的通信,但是浏览器已经不再支持通过修改 document.domain 来绕开同源策略,所以报错了。

背景

Chrome: 2022 年 1 月宣布,将从Chrome 115 document.domain开始弃用设置。如果您的网站依赖于通过放宽同源政策,您需要立即采取行动。使用 document.domain 设置 document.domain = ...) 不会引发异常。它只会不再产生作用。

Edge:从 Microsoft Edge 版本 115 开始,将忽略使用 JavaScript 修改 document.domain 属性的尝试。 需要使用替代方法(如 postMessage() 或通道消息 API)进行跨源通信

为什么使 document.domain 不可变

某些网站设置为 document.domain 允许同一网站但跨源页面之间的通信。 通过设置 document.domain ,同一站点文档可以更轻松地进行通信。 由于此更改 放宽了同源策略,因此父页可以访问同一站点 iframe 的文档并遍历 DOM 树,反之亦然。

此方法很方便:但这会带来安全风险。

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

  • 打开chrome://flags/#origin-agent-cluster-default 选择启用

  • 在 DevTools 问题面板查看告警

image.png

会影响哪些 JavaScript 的 API

JavaScript 的 API 中,如 iframe.contentWindow、 window.parentwindow.open 和 window.opener 允许文档间直接相互引用。当两个文档的源不同时,这些引用方式将对 Window 和 Location 对象的访问添加限制

Window

允许以下对 Window 属性的跨源访问:

方法
window.blur
window.close
window.focus
window.postMessage

属性
window.closed 只读。
window.frames 只读。
window.length 只读。
window.location 读/写。
window.opener 只读。
window.parent 只读。
window.self 只读。
window.top 只读。
window.window 只读。

某些浏览器允许访问除上述外更多的属性。

Location

允许以下对 Location 属性的跨源访问:

方法
location.replace

属性
HTMLAnchorElement.href 只写。

某些浏览器允许访问除上述外更多的属性。

可使用的替代方案

目前,你有两个选项可以替换 document.domain , 在大多数用例中,跨源 postMessage () 或 通道消息 API 可以替换 document.domain 以下是使用 postMessage() 的步骤,而不是 document.domain 用于跨源 DOM 操作。

  1. https://parent.example.com 通过 postMessage() 将消息发送到 iframe,其中包含 https://video.example.com 要求其修改其自己的 DOM。
// Configure a handler to receive messages from the subframe.
iframe.addEventListener('message', (event) => { 

// Reject all messages except from https://video.example.com 
  if (event.origin !== 'https://video.example.com') return;
  
  // Filter success messages 
    if (event.data === 'succeeded') { 

    // DOM manipulation is succeeded 

  } 

}); 

// Send a message to the subframe at https://video.example.com

iframe.postMessage('Request DOM manipulation', 'https://video.example.com');
  1. https://video.example.com 操作其 DOM,并使用 postMessage 来通知父级其成功。
// Configure a handler to receive messages from the parent frame.
window.addEventListener('message', (event) => {
 
  // Reject all messages except ones from https://parent.example.com 
  
  if (event.origin !== 'https://parent.example.com') return;
  
  // Perform requested DOM manipulation on https://video.example.com.
  
  if (event.data === "showTheButton") {
     document.getElementById('btnContinue').style.visibility = 'visible';
     // Send a success message back to the parent.

     event.source.postMessage('succeeded', event.origin); 
  }
});

如果有充分的理由继续设置 document.domain,则可以在返回HTML文件上增加 Origin-Agent-Cluster: ?0 响应头

Origin-Agent-Cluster: ?0

响应头 Origin-Agent-Cluster 指示浏览器文档是否应由源密钥代理群集处理。 若要详细了解 Origin-Agent-Cluster,请阅读 使用 Origin-Agent-Cluster 标头请求性能隔离