你听说 chrome 最新引入的特性 ”unpartitioned third-party storage“ 了么?

chrome 在 115 版本引入了一个和 iframe 息息相关的新特性,叫做 unpartitioned third-party storage,虽然不是什么重大更新,但是这个还真有可能一不小心给我们的工作埋下暗坑,如果你项目里用到 iframe 集成其他项目的页面了,还正好涉及到了一些单点登录相关的功能,那为了避免喜提来自 chrome 的工作量,咱还是来了解一下比较好。

这是个什么东西?

首先我们要知道的是,在老版本的 chrome 中,localstorage 的访问只和所处页面是否同源有关,只要地址是同源的,比如 example.com。那么无论你访问的是下面哪种情况:

这三个 example.com 读写的 localstorage 实际上是通用的,我们可以写一个 demo 证明一下。

由于这个特性是默认开启的,所以如果你的版本大于 115 的话,就需要先访问 chrome://flagsExperimental third-party storage partitioning 设置为 Disabled。

假设我们有两个网站,b.html 长这样,它可以更新 localstorage 里一个名为 token 的字段。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>网站B</title>
</head>

<body>
  <h1>网站B</h1>
  <button id="update-btn">刷新 token</button>
  <button id="open-btn">新标签页打开网站B</button>
  <p id="show">当前 localstorage 中 token 的值为:</p>
  <input placeholder="设置 localstorage token" id="my-input" />
  <button id="save-btn">保存</button>
</body>
<script>
  const readLocalstorage = () => {
    const value = localStorage.getItem('token')
    document.getElementById('show').innerText = `当前 localstorage 中 token 的值为:${value}`
  }

  document.getElementById('save-btn').addEventListener('click', () => {
    const value = document.getElementById('my-input').value
    localStorage.setItem('token', value)
    readLocalstorage();
  })

  document.getElementById('open-btn').addEventListener('click', () => {
    window.open('http://localhost:9876', '__blank');
  })

  document.getElementById('update-btn').addEventListener('click', () => {
    readLocalstorage();
  })

  readLocalstorage();
</script>
</html>

以及 a.thml,它只是单纯的用 iframe 集成了 b.html:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网站A</title>
</head>
<body>
  <h1>网站A</h1>
  <iframe src="http://localhost:9876" style="height: 100vh;width: 80vw;"></iframe>
</body>
</html>

现在我们用 serve 分别把 a.html 暴露在 127.0.0.1:9875,把 b.html 暴露在 127.0.0.1:9876。然后访问一下 a.html:

可以看到,不管有没有被 iframe 嵌套,127.0.0.1:9876 中的 b.html 始终可以访问到自己域下的最新 localstorage。

那如果把 Experimental third-party storage partitioning. 打开呢?

iframe 里边的 b.html 和直接标签页打开的 b.html 能访问到的 localstorage 被隔离开了,它们两个访问到的不再是同一个,而是各自独立的 localstorage。

开启了 Experimental third-party storage partitioning,被 iframe 集成的网站的域会变成类似于 a.com/b.com,而直接打开的网站的域则是 b.com,两者互相独立。

关于这个特性的官方介绍在 Participate in deprecation trial for unpartitioned third-party storage, Service Workers, and Communication APIs - Chrome for Developers

会导致什么问题?

现在可以回想一下,你项目里有没有用 iframe 接入过其他项目的某个页面,并且当外部页面登录之后,会通过单点使得 iframe 里边的页面也完成登录。

如果有的话,那 iframe 里的页面如果执行了类似于 window.open 的操作,那大概率就会触发这个问题。

具体表现就是:本来我操作的页面(嵌在 iframe 里)是已经登录的,但是当打开一个新窗口后,突然弹回到登录页了。明明原来的页面登录状态还没有掉,新开的窗口页为什么一直提示未登录呢。

原因很简单,前端的登录状态一般都是通过把 token 保存在 localstorage 里实现的。而新开的窗口页无法访问到 iframe 里保存的 localstorage token 字段。就认为系统未登录了。

怎么解决?

有三种方案,第一种是临时过渡方案:参考 这里的方法

根据你的情况从对应的链接里申请一个 token,然后放在你的网站上。之后这个检查就会被临时解除。但是要注意,最晚到 2024 年 9 月 4 号,这个方案就会被彻底关闭(这个实验特性被实装),所以你需要评估一下。

第二种方案要求你能修改 iframe 内嵌网站的代码,判断自己是否被 iframe 集成了,如果是的话就不在跳转,而是对外 postmessage,让 iframe 外边的网站再走一遍单点流程然后 window.open 就行了。

第三种方案就是通过 nginx 反代,把 iframe 里边集成的项目跟你外部的项目搞成同源的,这就彻底没这个问题了,但是改造成本可能不低。你可能得处理诸如字体、图片、接口请求、前端静态资源等一系列加载问题。

一些细节

当一个嵌在 iframe 里的页面触发了这个特性时,在 localstorage 里会将其标注为 is-third-party

并且,这个特性的触发标准是 top-level origin,而不是我们所熟知的同源策略 same-site origin。所以你可以发现哪怕端口不同(不同源),我们实际上也不会触发这个特性:

参考

相关推荐
T0uken16 小时前
【Python】UV:单脚本依赖管理
chrome·python·uv
powerfulzyh3 天前
Docker中运行的Chrome崩溃问题解决
chrome·docker·容器
代码的乐趣3 天前
支持selenium的chrome driver更新到136.0.7103.92
chrome·python·selenium
努力学习的小廉3 天前
深入了解linux系统—— 自定义shell
linux·运维·chrome
fenglllle4 天前
macOS 15.4.1 Chrome不能访问本地网络
chrome·macos
yousuotu4 天前
python如何提取Chrome中的保存的网站登录用户名密码?
java·chrome·python
颜淡慕潇5 天前
【Python】超全常用 conda 命令整理
chrome·python·conda
网硕互联的小客服5 天前
如何解决 Linux 系统文件描述符耗尽的问题
linux·运维·chrome
海尔辛5 天前
学习黑客正经版Bash 脚本入门教程
chrome·学习·bash
@PHARAOH5 天前
HOW - 在 Mac 上的 Chrome 浏览器中调试 Windows 场景下的前端页面
前端·chrome·macos