打印

CH9004: IE Firefox 在进行某些跳转时请求头中不会附加 Referer 字段信息

作者:陆远

标准参考

根据 HTTP1.1 规范中的描述,请求头中的 Referer 字段允许用户端为服务端指定得到的请求 URI 的资源地址 (URI),允许服务端生成资源的反向链接列表,同时也允许追踪维护过时的或者是拼写错误的链接。若一个请求 URI 获得自一个没有自身 URI 的源,则该请求 URI 的 Referer 字段不得被发送,如来自用户键盘的输入。

Referer = "Referer" ":" ( absoluteURI | relativeURI )

如:Referer: http://www.w3.org/hypertext/DataSources/Overview.html

关于 Referer 的更多信息,请参考 Hypertext Transfer Protocol -- HTTP/1.1 规范 14.36 Referer 中的内容。

问题描述

IE6 IE7 IE8 始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中。在普通页面中,当脚本调用 location 对象进行跳转时也不会附加 Referer 字段信息;
Firefox 始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中。

造成的影响

若服务端依靠请求头中的 Referer 字段信息进行某些操作,则在使用 META 元素进行页面跳转以及脚本 location 对象进行跳转时在某些浏览器中由于无 Referer 字段而产生差异。

受影响的浏览器

IE6 IE7 IE8  
Firefox  

问题分析

创建一个 Web 服务器,如 Apache。在服务器上编写一段动态代码,用于输出接收到的请求头的 Referer 字段信息。如:refer.php

<?php echo '<style>* { font:12px "Trebuchet MS"; }</style>'; echo
                (isset($_SERVER['HTTP_REFERER'])) ? 'Referer: ' . $_SERVER['HTTP_REFERER'] : 'Referer: N/A';
                ?>

本文中将测试 5 种常见的跳转方式,并分别在普通页面及 IFRAME 框架页内测试这些跳转方式下请求头 Referer 字段的发送情况。

5 种跳转方式代码:

anchor.html
<a href="refer.php">Anchor</a>
form_submit.html
<body> <form action="refer.php"><input
                    type="submit" /></form> <script> document.forms[0].submit();
                    </script> </body>
meta.html
<meta http-equiv="refresh" content="1;url=refer.php">
http302.php
<?php header('Location: refer.php'); ?>
location.html
<script>location.href="refer.php";</script>

测试页面:

index.html
<!DOCTYPE html> <html> <head> <base target="_blank" />
                    <style> * { margin:0; font:16px 'Trebuchet MS'; } </style> </head> <body>
                    <a href="anchor.html">Anchor</a><br /> <a
                    href="form_submit.html">Form submit</a><br /> <a
                    href="meta.html">META</a><br /> <a href="302.php">HTTP
                    302</a><br /> <a href="location.html">location.href</a>
                    </body> </html>
iframe.html
<!DOCTYPE html> <html> <head> <style> * { margin:0; font:16px
                    'Trebuchet MS'; } iframe { width:400px; height:40px; display:block; } </style> </head>
                    <body> <h1>Anchor:</h1> <iframe id="anchor" name="anchor"
                    scrolling="no" frameborder="0" src="anchor.html"></iframe>
                    <h1>Form submit:</h1> <iframe id="form_submit" name="form_submit"
                    scrolling="no" frameborder="0"
                    src="form_submit.html"></iframe> <h1>META:</h1> <iframe
                    id="meta" name="meta" scrolling="no" frameborder="0"
                    src="meta.html"></iframe> <h1>HTTP 302:</h1> <iframe
                    id="http302" name="http302" scrolling="no" frameborder="0"
                    src="302.php"></iframe> <h1>location.href:</h1> <iframe
                    id="loc" name="loc" scrolling="no" frameborder="0"
                    src="location.html"></iframe> </body> </html>

在各浏览器中分别打开上表的 "index.html"、"iframe.html",对于页面 "anchor.html" 需要用户手动点击超链接。

这段代码在不同的浏览器环境中的表现:

  IE6 IE7 IE8 Firefox Chrome Safari Opera
index.html 普通超链接 anchor.html OK OK OK
表单提交 form_submit.html OK OK OK
META 跳转 meta.html Fail Fail OK
HTTP 302 跳转 302.php OK OK OK
脚本 location.href 跳转 location.php Fail OK OK
iframe.html 普通超链接 anchor.html OK OK OK
表单提交 form_submit.html OK OK OK
META 跳转 meta.html Fail Fail OK
HTTP 302 跳转 302.php OK OK OK
脚本 location.href 跳转 location.php OK OK OK

可见,对于普通超链接、表单提交、302 跳转,各浏览器均会在请求头附加 Referer 字段信息,而对于 META 元素控制跳转及通过脚本使用 location 对象进行跳转时:

  • IE6 IE7 IE8 中,始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中。在普通页面中,当脚本调用 location 对象进行跳转时也不会附加 Referer 字段信息;

  • Firefox 中,始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中;
  • Chrome Safari Opera 中,则对于测试的 5 种方式下均会附加 Referer 字段信息。

解决方案

若服务端需要获得正确的 Referer 字段信息,则应采用各浏览器均可以附加 Referer 字段信息的方式进行跳转。如,普通超链接、表单提交、HTTP 302 跳转。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.10
Chrome 7.0.544.0 dev
Safari 5.0.2
Opera 10.62
测试页面: index.html
iframe.html
本文更新时间: 2010-10-11

关键字

跳转 location href meta 302 referer request http form iframe