如何断开JavaScript弹窗与打开它的窗口之间的连接

10

我正在使用以下代码从我的主页面打开一个弹出窗口:

<a href="http://external.domain.tld/"
   onclick="window.open(this.href, '_blank', 
       'width=512,height=512,left=200,top=100');return false">
 Open popup
</a>

这个功能可以正常工作,但我的问题是,在弹出窗口中加载的文档有权限更改打开者窗口的位置。即使弹出窗口中的文档来自不同的域,这也是有效的。它没有读取位置的权限,但允许更改位置。我不希望如此。我希望弹出窗口与我的主页面完全断开连接。

即使没有JavaScript,它也无法正常工作。当我使用target="_blank"属性在新标签页中打开其他页面时,该标签页仍然被允许导航到opener窗口并更改其位置:

<a href="http://external.domain.tld/" target="_blank">
  Open in new tab
</a>

这是在打开的文档中不应该被允许的代码:

<script>
  opener.location.href = "http://badsite.tld/";
</script>

您可以在这里查看实时演示。点击其中一个链接,以在弹出窗口或新标签页中打开另一个页面,然后在启动器窗口中加载第三个页面。这就是我想要防止的。

有没有什么技巧可以用来断开启动器窗口和已打开窗口之间的连接?理想情况下,已打开窗口应该完全不知道它是由任何其他窗口打开的。


您确信在这些域名上没有任何设置。其中一个是另一个的子域,通过特定设置,您可以访问到另一个域名。 - putvande
@putvande 是的,我确定。演示使用不同的子域(因为我只有一个域名的访问权限)。但是在生产服务器上,真正的问题使用完全不同的域名,并且没有任何特殊规则。打开的窗口没有权限从打开者窗口读取或调用任何内容,因此同源限制正常工作。它们只不过不适用于更改打开者窗口的位置href。 - kayahr
2个回答

18

如果子窗口中的页面在您的控制下,您可以将opener赋值为null:

window.opener = null;

在您的JavaScript中将此作为第一条语句。

如果页面不在您的控制范围内或位于不同的域中,则在打开时执行:

popup = window.open(this.href, '_blank', 'width=512,height=512,left=200,top=100');
popup.opener = null;

不幸的是,这不在我的控制范围内。我甚至尝试先打开一个中间页面,将window.opener设置为null,然后再加载其他页面。但是没有用,当新页面加载时,浏览器会恢复window.opener - kayahr
1
简单而优雅。完美运作。谢谢! - kayahr

2

来自文档:

在一些浏览器中,原始锚点标签上的 rel="noopener" 属性可以防止窗口的 opener 引用被设置。

支持该属性的浏览器列表: https://caniuse.com/#search=noopener

另外,在旧版浏览器中使用 no-referrer: https://mathiasbynens.github.io/rel-noopener/

因此,解决方法是在使用 target="_blank" 的地方添加 rel="noreferrer noopener" 属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接