前段时间需要通过 javascript 获取页面的来源,这个操作很简单,使用 document.referrer 就可以获取到了。不过,实际应用中还是有很多意外情况,这儿简单整理一下。
首先遇到的问题,是从 https 页面转到 http 页面后,document.referrer 的值为空。出于安全性考虑,很多网站的一些重要页面(比如淘宝的登录页面)都会使用 https 协议。如果某个未登录用户在页面 a(http 页面)点击了页面 b(http 页面)的链接,但页面 b 需要用户登录,于是先跳到登录页面 (https 页面),登录完成之后再跳回 b(http 页面),这时你会发现 b 页面上取不到 document.referrer 了。也就是说,如果想根据 referrer 来还原用户访问路径的话,如果路径中有 http 页面也有 https 页面,那么这个路径就会在从 https 到 http 的地方断掉。
这个问题的根源是浏览器的安全策略,只靠 javascript 似乎没有特别好的解决办法。一个迂回的思路是使用 window.name,在 https 页面将当前页面的 url 写到 window.name 中,再在下一个页面(http 页面)读取。
除了这种情况,其它页面跳转是否都能正常取到 document.referrer 呢?我搜索了一番,发现 这儿 有人整理了一个列表,不过不是很全,例如没有包括垂而不死的 ie6 的情况。于是便自己动手,在虚拟机里装了 n 个浏览器,把各种情况都测试了一下(这真是一个体力活),结果见下表:
操作 ie6 ie7 ie8 ie9 firefox chrome opera safari
直接在地址栏输入url “” “” “” “” “” “” “” “”
从书签访问url “” “” “” “” “” “” “” “”
从页面a点击超链接,跳转到页面b(target=”_self”) √ √ √ √ √ √ √ √
从页面a点击超链接,跳转到页面b(target=”_blank”) √ √ √ √ √ √ √ √
从页面a右键单击超链接,在新标签页中打开页面b - √ √ √ √ √ √ “”
从页面a右键单击超链接,在新窗口中打开页面b √ √ √ √ √ √ √ “”
拖动链接到地址栏 “” 无法拖动 无法拖动 “” “” “” “” “”
拖动链接到标签栏 - “” “” “” “” “” “” “”
使用浏览器的前进、后退按钮 √ √ √ √ √ √ √ √
js 修改 location.href “” “” “” √ √ √ √ √
js 使用 window.open “” “” “” “” √ √ √ √
服务器重定向(302跳转) 定向之前的页面 定向之前的页面 定向之前的页面 定向之前的页面 定向之前的页面 定向之前的页面 定向之前的页面 定向之前的页面
页面 meta refresh “” “” “” “” “” 转向页 转向页 转向页
上表中的“√”表示能正常取到 referrer,”” 表示 referrer 为空。
除了 ie 外,其它浏览器都是目前官网上能下载到的最新版本,其中 safari 同时测试了 windows 版和 mac 版,结论一样。
另外还有一些情况未做测试,例如点击 flash 跳转时各浏览器下能否保持 referrer 等。
上表中大部分情况是符合预期的,不过似乎也有几处需要注意的:
1、在 safari 中,右键打开链接会丢失 referrer;
2、在 ie 中,修改 location.href 或使用 window.open 打开页面会丢失 referrer(ie 9 有一点例外,使用 location.href 跳转不会丢失 referrer);
3、使用 meta 跳转时,ie / firefox 下会丢失 referrer。
最后,一个简单的结论是:如果你需要通过 document.referrer 采集页面访问来源,最好不要使用 js 跳转或打开新窗口,也不要使用 meta 跳转。