同一浏览器打开两个同源页面引发的bug【@码云 提个小优化】

简介: 同一浏览器打开两个同源页面引发的bug【@码云 提个小优化】

前端学习路线一条龙【内含入门到进阶到高级精选资源】无套路获取!!!

前端小菜鸡之菜鸡互啄,公众号:前端开发爱好者xy哥怒肝,前端学习路线一条龙【内含入门到进阶到高级精选资源】无套路获取!!!

哈喽,大家好 我是xy👨🏻‍💻。今天给大家来分享一个bug🐞。在同一浏览器打开两个同源页面发生的数据串改的问题,当然这篇文章只是用码云来举个例子,其它很多大型网站都中招了 💡

背景

一天下午,某某上帝(客户就是上帝)正在使用的我们公司的产品,在浏览器打开A标签页登录了a账号,然后又到B标签页登录了b账号,也就是同时登录了两个账号,然后到A下去操作数据(不刷新页面),结果造成了在A下修改到了B的数据,而且两个账号的权限还存在差异 💥

为什么会被串改

至于为什么会修改到 B 的数据:

前端把用户信息token 之类的是存储在浏览器本地的,这样一来,打开新的标签页登录其它账户,由于是同源页面,新的标签页的用户信息和token肯定会覆盖掉前一个标签页的用户信息和token,在页面不刷新的情况下,操作a账户下的数据,其实是操作的b下的数据

很多同学遇到这个问题的第一反应:

这个不是很正常的操作吗或者让用户刷新页面不就好了,包括我也是这样想的 🤣

同时也查看了市面上的一些产品,同样有类似的问题,就拿我们比较熟悉的 码云 来说吧,我特地的注册了两个账号

  1. 注册的新账号在第一个标签页登录image.png因为是全新的账号,没有任何信息之类的
  1. 打开新的标签页,先退出登录,然后登录我之前一直使用的账号

image.pngimage.png账户明明是新的账户,但是却把自己使用的旧账户的数据给展示过来了

当时心里暗喜,码云这么大的平台都没做处理,我们应该也无所谓了 ✌️

但是我就是个打工仔,搞不搞还不是领导说了算吗?既然领导已经提了这个需求,并且强烈要求优化用户体验,只能想办法解决喽 😩

需求方案

方案 1:

  • 同一浏览器支持同时登录两个账号,互不影响

方案 2:

  • 同一浏览器打开两个同源页面,把前一个标签页面提示用户强制刷新或者直接重定向到公司官网

回归问题本质

这个问题的本质其实就是:由于是同源页面,新的标签页的用户信息和token覆盖掉前一个标签页的用户信息和token

既然本质问题是本地存储替换的问题,那就想办法着手解决喽 🙍‍♂️

如何做到同时登录两个账号

做到两个账号同时登录互不干涉,其实只需要保证本地存储互不影响,让不同的用户存储的 token 的键名不一样

实现方法:在登录的时候存储用userName+token作为键来存储token

import Cookies from 'js-cookie'
export function setToken( token, userName ) {
  return Cookies.set( userName + 'token', token, { expires: xxxx } )
}

但是需要考虑到这个时候用户名:userName也可能会被覆盖,所以在每次刷新页面之前,把用户名存储到sessionStorage中去

window.addEventListener("beforeunload", () => {
  sessionStorage.setItem("userName", this.userName || "");
});

为什么要放到sessionStorage中呢 ?

💡 因为sessionStorage生命周期为当前窗口标签页,也就是每个标签页中的sessionStorage互不影响,即使是同源页面

获取 token 直接根据userName+token获取即可

export function getToken() {
  return Cookies.get( sessionStorage.getItem( 'userName' ) + 'token' )
}

好了,到这里基本上完美解决想要同一个浏览器登录多个用户账号的问题

前一个标签强制刷新或者重定向

再次回到问题本身,还是本地存储的问题。打开第二个同源页面标签页,有没有办法能够告诉第一个标签页呢???

当然有办法了,我们可以利用 HTML5 storage事件监听:

💡HTML5 storage事件监听:当同源页面的某个页面修改localStorage,其余的同源页面只要注册了storage事件,就会触发

Web Storage API内建了一套事件通知机制,当存储区域的内容发生改变(包括增加修改删除数据)时,就会自动触发 storage 事件,并把它发送给所有感兴趣的监听者。因此,如果需要跟踪存储区域的改变,就需要在关心存储区域内容的页面监听storage事件。

window.addEventListener("storage", (e)=>{
   // 获取 e 后做一系列判断操作
 }, false);

实际上,这个事件e上还带有很多信息,可以对事件做精确的控制 👇。

字段 含义
key 发生变化的 storageKey
newValue 变换后新值
oldValue 变换前原值
storageArea 相关的变化对象
url 触发变化的 URL,如果是 frameset 内,则是触发帧的 URL

有了这些内容,就可以根据自己的业务需求来做需要的操作了。

但是这里注意一个问题,只有当同源页面的某个页面修改localStorage,也就是不修改,还是监听不到的。

如果直接把第一个标签页的链接复制到第二个标签页,本地存储是不会更改的,这个时候第一个标签页的监听事件将不会触发

这个时候可以在每次页面初始化的时候在 localStorage 中写入一个唯一的标识,建议是时间戳之类的,这样即使把地址复制到第二个标签页中,也会执行初始化操作,时间戳改变就会触发监听的storage事件。

ok 了,问题统统解决

💡 最后想@码云以及很多存在此类问题的网站都提出这个优化点,2022,让我们变得更好吧 🤞。

相关文章
|
1月前
|
缓存 JavaScript
vue阻止浏览器刷新和关闭页面提示
使用场景:在使用vuex进行缓存管理时,页面的缓存会随着页面关闭而消失,如果缓存动作仍在进行中,关闭页面会导致数据丢失,此时需要阻止页面关闭
51 3
|
2月前
|
数据采集 Web App开发 JSON
浏览器插件:WebScraper基本用法和抓取页面内容(不会编程也能爬取数据)
本文以百度为实战案例演示使用WebScraper插件抓取页面内容保存到文件中。以及WebScraper用法【2月更文挑战第1天】
126 2
浏览器插件:WebScraper基本用法和抓取页面内容(不会编程也能爬取数据)
|
3月前
|
Web App开发 前端开发 搜索推荐
Chrome 浏览器中的一个隐藏设置页面
Chrome 浏览器中的一个隐藏设置页面
105 8
|
4月前
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
|
18天前
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
【超实用】Angular如何修改当前页面网页浏览器url后面?param1=xxx&param2=xxx参数(多用于通过浏览器地址参数保存用户当前操作状态的需求),实现监听url路由切换、状态变化。
|
19天前
|
搜索推荐 前端开发 UED
html页面实现自动适应手机浏览器(一行代码搞定)
html页面实现自动适应手机浏览器(一行代码搞定)
19 0
|
1月前
|
Web App开发 缓存 网络协议
|
3月前
|
搜索推荐 前端开发 UED
html页面实现自动适应手机浏览器(一行代码搞定)
html页面实现自动适应手机浏览器(一行代码搞定)
62 0
|
3月前
|
缓存 网络协议 前端开发
面试题:浏览器中输入URL返回页面过程?
面试题:浏览器中输入URL返回页面过程?
90 0
|
8月前
|
域名解析 JavaScript 前端开发
从浏览器地址栏输入url到显示页面的步骤?
1.浏览器根据请求的 URL 交给 DNS 进行域名解析,找到真实 IP 地址,向服务器发起请求 2.服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、CSS、JS、images等); 3.浏览器对加载到的资源(HTML、CSS、JS、images等)进行语法解析,建立相应的内部数据结构(如HTML的DOM); 4.载入解析到的资源文件,渲染页面,完成。
159 0

热门文章

最新文章