【问题标题】:Google Chrome: Accessing window.opener for target="_blank" link after rel="noopener" is the new defaultGoogle Chrome:在 rel="noopener" 之后为 target="_blank" 链接访问 window.opener 是新的默认设置
【发布时间】:2021-09-14 23:13:55
【问题描述】:

我刚刚了解了rel="noopener" 属性,它使打开的窗口不知道它们的开启器。我玩了一下,一直得到window.opener === null,直到我发现它现在是所有现代浏览器的新默认值。

现在,我想实际阅读window.opener 属性,看看它是如何工作的:

<!-- http://opener-from.test/ -->
<a href="http://opener-to.test/" target="_blank">no rel</a>
<a href="http://opener-to.test/" target="_blank" rel="opener">rel="opener"</a>
<a href="http://opener-to.test/" target="_blank" rel="noopener">rel="noopener"</a>
<!-- http://opener-to.test/ -->
<script>
console.log(window.opener);
</script>

no relrel="noopener" 链接只会使目的地获得 window.opener === null。至于rel="opener",它在 Firefox 和 Safari 上运行良好,但在 Google Chrome 中我得到了错误:

Uncaught DOMException: Blocked a frame with origin "http://opener-to.test" 访问跨域框架。

我在 Chrome 91 中对其进行了测试。如何在 Google Chrome 中的 target="_blank" 上下文中访问 window.opener

【问题讨论】:

  • 关于错误消息的(来源)不清楚的地方 - "Blocked a frame with origin "opener-to.test" from access a cross-原框架" ?
  • 问题是如何允许来自opener-to.test
  • @sideshowbarker 我在写我的之前已经看过这篇文章。仍然不明白为什么 Chrome 会抛出错误,而其他浏览器则不会。

标签: javascript html google-chrome same-origin-policy window.opener


【解决方案1】:

这与默认rel无关,与跨域访问有关。来自MDN's documentation for opener

如果打开器与当前页面不在同一个来源,则打开器对象的功能受到限制。例如,window对象上的变量和函数是不可访问的。但是,打开器窗口的导航是可能的,这意味着打开的页面可以在原来的选项卡或窗口中打开一个URL。 p>

(我的重点)

console.log(window.opener) 将尝试访问 window.opener 上的属性。

拥有rel="opener" 可以在开启程序中进行导航,但不能访问该窗口公开的全局变量(包括函数)。它还可以使用postMessage 与开启者窗口对话。

如果您只想查看是否可以访问 opener,请改为使用 console.log(window.opener === null) 并查看是 true(您没有访问权限)还是 false(您的访问权限有限)。

尽管使用rel="opener",但它的访问权限受限,如上面的 MDN 引用所示。您无法获得对 window.opener 跨域(仅同源)的完全访问权限。

这种只允许有限访问对象内容的能力不仅仅是浏览器可以做到的魔法,你可以通过Proxy在JavaScript本身中做到这一点:

const realOpenerWindow = {
    x: 42,
};

const opener = new Proxy(realOpenerWindow, {
    get(target, property, receiver) {
        if (allow) {
            return Reflect.get(target, property, receiver);
        }
        throw new Error(`Access is disallowed`);
    }
})


let allow = true;
console.log(opener === null); // false
console.log(opener.x);        // 42
allow = false;
console.log(opener === null); // false
console.log(opener.x);        // Throws error

关于为什么 Chrome 会出现错误,但 Firefox 等非 Chromium 浏览器不会:不同的控制台实现方式不同。显然 Firefox 的控制台是为了向您展示它允许向您展示的内容,但 Chrome 只是应用其通常的对象处理并触发访问错误。

【讨论】:

  • 谢谢,我不确定它是否回答了我的主要问题。我只是在了解它并在 Chrome 中访问 window.opener 会引发错误。它不会在其他浏览器中抛出。我还没有检查这个对象中有什么和没有什么。
  • @RoboRobok - 是的,你是 - 正如我所说,console.log 将尝试访问窗口的属性,因为这就是当你传递一个对象时它所做的。如果你只是想看看你是否可以访问opener,请做console.log(window.opener === null) 看看它是真是假。
  • 再次,如果它在 Chrome 中引发错误,我该怎么办?我的问题是不是说得那么糟糕?
  • @RoboRobok - 再次,console.log(window.opener === null)
  • 我会做更多的实验,让你知道结果如何:) 到目前为止谢谢!
猜你喜欢
  • 2018-11-15
  • 2019-02-15
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
相关资源
最近更新 更多