坑点and埋坑点 - header重定向后取不到referer ¶
作者:KK
发表日期:2016.12.23
要点速读 ¶
如果从a.php执行header('Location: b.php');
跳转到b.php后,在b.php里echo $_SERVER['HTTP_REFERER'];
通常情况下会提示undefined
注意只是通常情况下
也结合此文:《HTTP请求头与SERVER数组》可以知道,我们访问$_SERVER['HTTP_REFERER']
时始终都应该加isset判断
准备测试代码 ¶
先给出以下三个文件的代码
a.php:
header('Location: b.php');
到b.php:
echo $_SERVER['HTTP_REFERER'];
index.php:
<script src="http://www.kkh86.com/js/jquery-1.11.1.min.js"></script>
<script>
location.href = 'a.php';
/*
$.ajax({
url : 'a.php',
success : function(result){
console.log(result);
}
});
*/
</script>
<a href="index.php">和JS跳一样的效果,反正都是通过document来跳</a>
开始测试 ¶
测试方式1:直接请求带有header跳转的地址(a.php)
访问a.php就会马上执行header,结果去了b.php后提示undefined
结论:访问的地址如果有
header('Location:$url')
的时候,跳转的目标地址不会收到referer这个请求头
测试方式2:通过JS代码跳转到a.php
访问index.php就会执行location.href跳转,然后也是到了b.php但却看到了
$_SERVER['HTTP_REFERER']
的值结论:用前端跳转就可以有referer,可以初步猜测referer是浏览器包装后才发给后端的
测试方式3:用ajax请求a.php
再把index.php的location.href注释掉,换成下面的ajax代码请求a.php,也会看到返回值
并且会看到有两个请求地址,第一个地址是“a.php”的(并且没有响应内容,看响应头),第二个就是“b.php”
之所以一次ajax产生2次请求,是因为ajax在收到
Location
这个响应头后就自动再发了个请求给重定向的地址,因为在ajax的理解里应该是“是服务端让我掉头找另一个地址要数据的”
测试方式4:点击a标签跳转到a.php
结果也是输出了referer
最终的简单结论就是:如果直接访问的地址就响应了Location
这个报头字段,则浏览器马上请求的新地址无法获取到referer
相关参考:RFC 1945号文档第10.13章节提到referer这个请求头字段是允许客户端发给服务端的
真相
:其实referer通常是要document发出请求才有的,而直接请求一个地址时如果还没输出HTML就先发了报头,此时document对象还未产生,所以这个跳转无法构造referer发给服务端。本文章的测试方式2、3、4中能让服务端得到referer字段正是因为它们是在浏览器已经构造了document对象之后通过前端代码发出请求的