javascript的document.referrer浏览器支持、失效情况总结_基础知识

在流量统计服务中都有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,用于判断访客是从哪个页面发起的请求。

一般情况下浏览器请求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添加进头部。

时间: 2024-10-03 14:24:56

javascript的document.referrer浏览器支持、失效情况总结_基础知识的相关文章

整理的比较不错的JavaScript的方法和技巧第1/3页_基础知识

适合阅读范围:对JavaScript一无所知-离精通只差一步之遥的人 基础知识:HTML JavaScript就这么回事1:基础知识  1 创建脚本块 1: <script language="JavaScript"> 2: JavaScript code goes here 3: </script>  2 隐藏脚本代码 1: <script language="JavaScript"> 2: <!-- 3: documen

JavaScript中的条件判断语句使用详解_基础知识

 在写一个程序,可能有一种情况,当你需要采用一个路径出给定两个路径.所以,需要使用条件语句,让程序来做出正确的决策和执行正确的行动. JavaScript支持其用于执行根据不同的条件不同的操作条件语句.在这里,我们将解释if..else语句. JavaScript支持if..else语句的形式如下:     if 语句     if...else 语句     if...else if... 语句. if 语句: if语句是基本的控制语句,它允许JavaScript来作出决定,有条件地执行语句.

Javascript中Date类型和Math类型详解_基础知识

Date类型 ECMASCript中的Date类型是在早期中Java中的java.util.Date类基础上构建的.为此Date类型使用自UTC(国际协调时间)1970年1月1日午夜(0时)开始经过的毫秒数来保存日期. 创建日期对象 1.创建当前日期.不需要传入参数 2.创建指定日期.需要传入参数,必须传入表示该日期的毫秒数(即从1970年1月1日午夜起至该日期止经过的毫秒数).为了简化这一计算过程,ECMAScript提供了两个方法:Date.parse()和Date.UTC(). var n

JavaScript程序中实现继承特性的方式总结_基础知识

概述JavaScript的所有对象,都有自己的继承链.也就是说,每个对象都继承另一个对象,该对象称为"原型"(prototype)对象.只有null除外,它没有自己的原型对象. 原型对象的重要性在于,如果A对象是B对象的原型,那么B对象可以拿到A对象的所有属性和方法.Object.getPrototypof方法用于获取当前对象的原型对象. var p = Object.getPrototypeOf(obj); 上面代码中,对象p就是对象obj的原型对象. Object.create方法

探讨JavaScript中的Rest参数和参数默认值_基础知识

Rest 参数 通常,我们需要创建一个可变参数的函数,可变参数是指函数可以接受任意数量的参数.例如,String.prototype.concat 可以接受任何数量的字符串作为参数.使用 Rest 参数,ES6 为我们提供一种新的方式来创建可变参数的函数. 我们来实现一个示例函数 containsAll,用于检查一个字符串中是否包含某些子字符串.例如,containsAll("banana", "b", "nan") 将返回true,contai

深入学习JavaScript中的Rest参数和参数默认值_基础知识

本文将讨论使 JavaScript 函数更有表现力的两个特性:Rest 参数和参数默认值.Rest 参数 通常,我们需要创建一个可变参数的函数,可变参数是指函数可以接受任意数量的参数.例如,String.prototype.concat 可以接受任何数量的字符串作为参数.使用 Rest 参数,ES6 为我们提供一种新的方式来创建可变参数的函数. 我们来实现一个示例函数 containsAll,用于检查一个字符串中是否包含某些子字符串.例如,containsAll("banana", &

Javascript中eval函数的使用方法与示例_基础知识

定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法 eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句. 返回值 通过计算 string 得到的值(如果有的话). 说明 该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回.因此请不要为 eval() 函数传递 String 对象来作为参数. 如果试图覆盖 eval

总结JavaScript三种数据存储方式之间的区别_基础知识

sessionStorage .localStorage 和 cookie 之间的共同点:都是保存在浏览器端,且同源的. sessionStorage .localStorage 和 cookie 之间的区别:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递.而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存.cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下. 存储大

Javascript中的几种继承方式对比分析_基础知识

开篇从'严格'意义上说,javascript并不是一门真正的面向对象语言.这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的区别,因而默认它就是非主流的面向对象方式,甚至竟有很多书将其描述为'非完全面向对象'语言.其实个人觉得,什么方式并不重要,重要的是是否具有面向对象的思想,说javascript不是面向对象语言的,往往都可能没有深入研究过javascript的继承方式,故特撰此文以供交流. 为何需要利用javascript实现继