你听说 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。所以你可以发现哪怕端口不同(不同源),我们实际上也不会触发这个特性:

参考

相关推荐
shimly1234562 小时前
bash 脚本比较 100 个程序运行时间,精确到毫秒,脚本
开发语言·chrome·bash
秃了也弱了。5 小时前
Chrome谷歌浏览器插件ModHeader,修改请求头,开发神器
前端·chrome
kingsley6 小时前
safari 浏览器的一次问题定位
浏览器
叶常落7 小时前
chrome插件合集
chrome
蓝天白云下遛狗7 小时前
goole chrome变更默认搜索引擎为百度
前端·chrome
拾光拾趣录10 小时前
JavaScript 加载对浏览器渲染的影响
前端·javascript·浏览器
代码讲故事13 小时前
多种方法实现golang中实现对http的响应内容生成图片
开发语言·chrome·http·golang·图片·快照·截图
PeterJXL1 天前
Chrome 下载文件时总是提示“已阻止不安全的下载”的解决方案
前端·chrome·安全
今晚打老虎z1 天前
dotnet-env: .NET 开发者的环境变量加载工具
前端·chrome·.net
前端_逍遥生1 天前
Chrome 插件开发到发布完整指南:从零开始打造 TTS 朗读助手
前端·chrome