我们有一个后台管理系统,用户信息存储在localStorage中,用户id存储在sessionStorage中,用户登录后根据用户id去localStorage中取对应的用户信息。
今天进行第二轮提测,提测完发现有的页面跳转会自动跳转到登录页。并且接口有时会报401,后端表示没有传token过去。检查了一下是router-link的target="_blank"跳转导致的问题,奇怪的是这块代码本次提测根本没动过,一周前的一轮提测是没问题的。
于是简单定位一下,页面先是跳转到对应的页面然后又跳到了登录页。是否是路由重定向的问题,看了一下路由配置是对的,这块儿代码也没动过。
奇怪的是我的浏览器不管是本地环境还是开发环境、测试环境都是没问题的,测试同事和前端同事的电脑运行都有问题。前端同事提示是否是浏览器版本问题,于是我将chrome升级到了最新的89版本,果然我的chrome也出问题了,点击打开新页面的按钮直接跳到了登录页。
我们大概定位了一下,跳转登录页的代码只有两个地方写了,一个是获取用户信息时如果session里没有用户id,另一个是全局的main.js中获取session里的用户id,没有获取到都会跳转登录页。这样写的目的是为了防止用户未登录的情况下进入到项目里。
我们将跳转登录页的两处代码注释掉,果然问题解决了,可以正常跳转页面!!!
原来问题出在跳转新标签页时session里的用户id没获取到。
chrome跳转新标签页时如果两个标签页是同样的域名是会共用session的,也就是说跳转后的新页面按道理来说可以拿到用户id。可偏偏chrome在89版本的更新中进行了更改,见下图。
Chrome更新89版本后,sessionStorage丢失a标签跳转丢失sessionStorage - SegmentFault 思否

chrome89后的版本默认将a标签跳转时加了rel="noopener",导致新标签页的session被清掉了。
解决办法非常简单:给a标签或者router-link手动加上rel="opener"。
谷歌为什么要这么做?保留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 对象。很安全!
网友评论