javascript的document.referrer浏览器支持、失效情况总结


Posted in Javascript onJuly 18, 2014

在流量统计服务中都有Traffic source这个功能。Traffic source是针对访次级别的概念,换句话说,当访次建立的时候,landing page的流量来源即是该访次的Traffic source。虽然Traffic source有很多种,不过不幸的是依据现在JS,获得Traffic source的途径只有两种——document.referrer、window.opener.更不幸的是,window.opener适用的场景不多,而document.referrer非常的弱,以至于很多场景下无法准确判断出流量来源。

document.referrer的覆盖

从使用意义上来说document.referrer希望能够追踪到的是浏览器端行为。如果一张页面A被打开,那么浏览器端可能会发生的动作有用户操作、JS代码两种。

先来看看用户打开页面A可能会进行的操作:

1 直接在地址栏中输入A的地址
2 从B页面左击link A,跳转至A页面
3 从B页面右击link A,在新窗口中打开
4 从B页面右击link A,在新标签页中打开
5 拖动link A至地址栏
6 拖动link A至标签栏
7 使用浏览器的前进、后退按钮

注意这里的link即指<A>标签,但是如果有事件或者target还要另当别论。

JS打开页面可能的方式:

1 修改window.location
2 使用window.open
3 点击flash

上面列出了客户端打开页面的一些方法,此外,如果通过服务端的重定向技术,也能够使得页面A呈现给访客。

下面来针对具体的浏览器测试,如果是上述的这些情况,document.referrer表现如何:

序号 场景 IE8.0 FF3.6 FF4.0 chrome
1 直接在地址栏中输入A的地址 " " " " " " " "
2 从B页面左击link A,A页面替换B页面(target='_self')
3 从B页面左击link A,A在新窗口中打开(target='_blank')
3 从B页面右击link A,在新窗口中打开 " "
4 从B页面右击link A,在新标签页中打开 " "
5 鼠标拖动link A至地址栏 " " " " " "
6 鼠标拖动link A至标签栏 " " " " " " " "
7 使用浏览器的前进、后退按钮 保持 保持 保持 保持
8 修改window.location打开A页面(同域) " "
9 使用window.open打开A页面 " "
10 点击flash打开A页面
11 服务器重定向至A页面 " " " " " " " "

其中," "表示一个空的字符串,√表示能够正确判断来源页,保持则意味使用前进后退不会改变页面的referrer。从这张表里可以看出document.referrer能覆盖大约一半的case。但是对于一些比较常用的操作,例如利用鼠标拖动link至标签栏、前进后退等情况还不能做出正确的处理。

document.referrer的来源

浏览器在向server请求页面A的时候,会发送HTTP请求。这个请求的Header里会带上Referer属性,server接收到该请求后,可以提取出Header里的Referer,用于判断访客是从哪个页面发起的请求。

javascript的document.referrer浏览器支持、失效情况总结

一般情况下浏览器请求A时发送的Header中Referer是什么,那么拿到A页面后document.referre的值就是什么。上图是一个请求A页面的Header,A的document.referre为http://localhost/Test/b.html。
 
如果在Header中不包含Referre,那么用document.referre去取的时候,就会被赋值为空字符串。

关于HTTPS请求

如果在一张普通的HTTP页面上点击了HTTPS的链接,那么在https请求头部可以附上Referer信息,之后在HTTPS页面中依然可以用document.referre来获得普通的http页面。
 
同样,如果是在一张https页面上点击了另一个HTTPS的链接,可以在请求的头部附上Referer信息。
 
但是如果是从一张https页面点击了http链接,那么很不幸,发送的http请求头里无法包含关于https页面的信息,这可能是出于一种对https页面的保护措施。

伪造Referer信息

根据上文的描述,document.referre源自于Header中的Referer。那么如果想修改document.referre的值,理论上讲,仅需要修改请求Header。可以将Header中现有的Referer替换成自己想要的值,如果原来没有也可以添加Referer。
 
在客户端,篡改Header是一件非常容易的事情。在一个页面的http请求发出去之前,可以利用截包工具将其拦截,然后分析出头部信息,并且修改Referre。
 
搜了一下,对于FireFox可以使用RefControl插件方便的进行修改。总之,欺骗Traffic source是轻而易举的事情。

页面强制Refresh

写完不久就发现遗漏了一种页面跳转的方式,即在html中的meta标签里强制指定页面进行refresh。例如在b.html中写入

<meta http-equiv="Refresh" content="5;URL=a.html">

则过5秒后浏览器会自动向server发起a页面请求。
 
经过测试,在IE8,FF3.6-FF4.0中,均不会带有Referer信息,但是chrome却能够鬼使神差的把b.html作为Referer添加进头部。
Javascript 相关文章推荐
JS实现点击图片在当前页面放大并可关闭的漂亮效果
Oct 18 Javascript
JS获取下拉列表所选中的TEXT和Value的实现代码
Jan 11 Javascript
jquery validate 自定义验证方法介绍 日期验证
Feb 27 Javascript
新手快速学习JavaScript免费教程资源汇总
Jun 25 Javascript
JavaScript实现动态添加,删除行的方法实例详解
Jul 02 Javascript
JS组件Bootstrap实现弹出框和提示框效果代码
Dec 08 Javascript
js获取iframe中的window对象的实现方法
May 20 Javascript
Bootstrap布局组件教程之Bootstrap下拉菜单
Jun 12 Javascript
JS+HTML5手机开发之滚动和惯性缓动实现方法分析
Jun 12 Javascript
Node.js用readline模块实现输入输出
Dec 16 Javascript
微信小程序 数据遍历的实现
Apr 05 Javascript
MockJs结合json-server模拟后台数据
Aug 26 Javascript
jQuery控制的不同方向的滑动(向左、向右滑动等)
Jul 18 #Javascript
JQuery对表单元素的基本操作使用总结
Jul 18 #Javascript
jQuery新的事件绑定机制on()示例应用
Jul 18 #Javascript
jQuery中attr()和prop()在修改checked属性时的区别
Jul 18 #Javascript
$.each遍历对象、数组的属性值并进行处理
Jul 18 #Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
Jul 17 #Javascript
一个小例子解释如何来阻止Jquery事件冒泡
Jul 17 #Javascript
You might like
对javascript和select部件的结合运用
2006/10/09 PHP
Php 构造函数construct的前下划线是双的_
2009/12/08 PHP
PHPMYADMIN导入数据最大为2M的解决方法
2012/04/23 PHP
根据中文裁减字符串函数的php代码
2013/12/03 PHP
php实现加减法验证码代码
2014/02/14 PHP
ThinkPHP3.1新特性之对页面压缩输出的支持
2014/06/19 PHP
php上传中文文件名乱码问题处理方案
2015/02/03 PHP
laravel框架实现去掉URL中index.php的方法
2019/10/12 PHP
thinkphp5实现微信扫码支付
2019/12/23 PHP
jquery全选checkBox功能实现代码(取消全选功能)
2013/12/10 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
2014/06/04 Javascript
JavaScript中的style.cssText使用教程
2014/11/06 Javascript
JS简单计算器实例
2015/01/20 Javascript
Javascript中String的常用方法实例分析
2015/06/13 Javascript
jQuery validate插件submitHandler提交导致死循环解决方法
2016/01/21 Javascript
JS图片左右无缝隙滚动的实现(兼容IE,Firefox 遵循W3C标准)
2016/09/23 Javascript
bootstrap switch开关组件使用方法详解
2017/08/22 Javascript
浅谈Vue下使用百度地图的简易方法
2018/03/23 Javascript
vue中v-text / v-html使用实例代码详解
2019/04/02 Javascript
基于Vue+elementUI实现动态表单的校验功能(根据条件动态切换校验格式)
2019/04/04 Javascript
[19:59]2014DOTA2国际邀请赛 IG战队纪录片
2014/08/07 DOTA
[00:53]2015国际邀请赛 中国区预选赛一触即发
2015/05/14 DOTA
python使用正则表达式分析网页中的图片并进行替换的方法
2015/03/26 Python
Python返回真假值(True or False)小技巧
2015/04/10 Python
pandas or sql计算前后两行数据间的增值方法
2018/04/20 Python
Python实现将多个空格换为一个空格.md的方法
2018/12/20 Python
Python3.7 dataclass使用指南小结
2019/02/22 Python
itchat-python搭建微信机器人(附示例)
2019/06/11 Python
使用Dajngo 通过代码添加xadmin用户和权限(组)
2020/07/03 Python
关于HTML5+ API plusready的兼容问题
2020/11/20 HTML / CSS
什么是Smarty变量操作符?如何使用Smarty变量操作符
2014/07/18 面试题
说出一些常用的类,包,接口
2014/09/22 面试题
学习计划书怎么写
2014/09/15 职场文书
2015年全民创业工作总结
2015/07/23 职场文书
创业不要错过,这4种餐饮新模式
2019/07/18 职场文书
python随机打印成绩排名表
2021/06/23 Python