如何防止在使用 target= "_blank" /window.open() 打开新窗口/选项卡时继承会话存储?



在带有url的选项卡上http://foo.com/我设置了一个会话存储项目,因此-

sessionStorage.bar="hello";

然后我在同一域上的任何路径上打开一个新窗口-

window.open("http://foo.com/any/path");

然后在新窗口上,我发现-

sessionStorage.bar === "hello"

是真的。如果我使用target="_blank"属性的链接打开新窗口,也会发生完全相同的情况。当打开一个新选项卡而不是一个新窗口时,也会发生完全相同的事情。另一件需要注意的事情是,这只适用于打开新窗口之前在sessionStorage上设置的项目。在打开新窗口后,在任一窗口中添加或更改sessionStorage上的任何项目不会以任何方式影响另一个窗口。

我认为sessionStorage的范围应该是一个选项卡/窗口,但显然,当从另一个窗口打开新的选项卡和窗口时,sessionStorage会扩展到它们。

有办法防止这种情况发生吗?我可能可以测试window.opener的存在来检测这样的情况,但如果能从一开始就预防的话,它会干净得多。

谢谢!

根据Webstorage规范,"当在具有顶级浏览上下文的浏览上下文中创建新文档时,用户代理必须检查该顶级浏览上下文是否有该文档来源的会话存储区域。如果有,则这是文档分配的会话存储区。">

因此,我对此的看法是,如果您关闭选项卡,然后打开一个新的选项卡,根据规范,这将是一个新"会话"。但是,如果选项卡保持打开状态,然后打开一个新选项卡,则顶级浏览上下文将匹配,因此会话存储将被引用。

您可以使用这种方式:

const a = document.createElement('a');
a.href = "http://example.com/any/path";
a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);

您可以通过将window.open-windowFeatures参数'noopener'设置为true:来防止新选项卡或窗口继承原始窗口会话的副本Storage

window.open('http://example.com', '_blank', 'noopener=true');

参数"noreferrer"也起作用,因为如果设置,浏览器将省略Referer标头,并将noopener设置为true。

用于window.open 的Mozilla文档

注意:当使用window.open在同一窗口(即当前窗口,目标设置为"_self")中打开URL时,此参数不是解决方案。尽管重新分配的窗口不会有window.opener值,但由以前的URL设置的会话存储可能会保留下来——至少在新URL具有相同域的情况下是这样。

我通过在打开新窗口时临时删除会话项来解决这个问题。

sessionStorage.removeItem('bar');
window.open('http://example.com/any/path', '_blank');
sessionStorage.setItem('bar', 'hello');

您可以通过在每个窗口中使用一个单独的键来解决继承行为(或者,如果您有多个键,则可以为每个键应用一些唯一的前缀)。

这就引出了如何为每个窗口分配/保留唯一密钥的问题。好吧,当在Internet Explorer的新选项卡中打开的链接显示您可以将每个窗口的名称设置为某个唯一值时,SessionStorage并不是空的,该值将在重新加载时保留。

最新更新