前言

最近在排查Safari隐私模式下页面参数丢失的问题,如果通过Safari直接打开B页面,此时在B页面可以正常获取到页面链接上的参数,但是如果Safari先打开A页面,然后通过A页面再跳转到B页面(A、B页面部署在不同域名下),此时的B页面通过JS就获取不到链接上的参数了🤔,这样就会导致一些依赖页面参数的功能出现异常!

问题演示

B页面链接格式如下:xx.qq.com?au=xx...

通过一下代码获取页面链接及页面参数:

console.log('link', window.location.href);
console.log('query', window.location.search);
  • 1.
  • 2.

如果是隐私模式下单独打开B页面

Safari 隐私模式下,URL 参数为何神秘消失?_Safari

此时可以看到是能够正常获取到页面完整链接(包括参数)的。符合预期

但是如果先打开A页面,再从A页面跳到B页面(A、B域名不同),我们再来看看结果:

Safari 隐私模式下,URL 参数为何神秘消失?_前端_02

从上图可以看到,此时location.search就已经获取不到了,location.href拿到的值也不再包括location.search了。

那么Safari在隐私模式下的这种做法是为了做什么呢?

Safari隐私浏览

通过查询资料后得知,在 Safari 17 中,隐私浏览功能更加私密,并新增了防御措施,以抵御一些最先进的追踪技术。技术改进包括:

  • 链接跟踪保护
  • 阻止已知跟踪器的网络负载,包括 CNAME 隐藏的已知跟踪器
  • 高级指纹保护
  • 具有网站或历史记录访问权限的扩展程序默认处于关闭状态

链接跟踪保护

Safari 的“隐私浏览”功能在用户浏览不同网站时,针对目标 URL 中的跟踪信息实施了两项新的保护措施。具体涵盖的 URL 部分包括查询参数和 URL 片段。这些保护措施旨在使目标网站上运行的第三方脚本更难以通过读取 URL 来关联跨网站的用户活动。

在文档上有这样一段话:

Safari 隐私模式下,URL 参数为何神秘消失?_html_03

翻译过来就是:在跨站导航后的目标网站上,所有尝试读取完整 URL或参数 的第三方脚本(例如使用 location.search、location.href 或 document.URL)都将获得一个不含查询参数或片段的 URL 版本。

也就是说Safari隐私模式下链接参数丢失必须满足以下两种情况:

  • 页面发生了跨域名跳转
  • 获取链接或参数在第三方脚本中执行(其实就是JS与html模版不在同一个域名下)

解决方案

同域跳转

既然不同发生跨域跳转,那么同域名跳转是不是就能正常获取页面链接参数了

Safari 隐私模式下,URL 参数为何神秘消失?_模版_04

同域部署

如果第一种方案满足不了业务场景,那么可以尝试将html模版文件与JS文件用相同域名部署,也能规避Safari隐私模式的限制

内联脚本

如果你的业务既要跨域跳转又不想改部署方案,那么内联脚本这种方案比较适合你,我们可以在html模版文件内插入一段JS脚本去获取页面链接及参数,这样的话这段JS就不属于第三方脚本了。

比如:

<!-- index.html -->
<script>
		window.selfLink = window.location.href;
    window.selfSearch = window.location.search;
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

然后再使用的地方直接读取window上的selfLinkselfSearch

console.log('link', window.location.href);
console.log('query', window.location.search);
console.log('--selfLink--', window.selfLink);
console.log('--selfSearch--', window.selfSearch);
  • 1.
  • 2.
  • 3.
  • 4.

Safari 隐私模式下,URL 参数为何神秘消失?_浏览器_05

可以看到通过读取内联脚本挂在window上的selfLinkselfSearch可以正常获取,而直接读取window.location.href会丢失search参数。