1

本人微信公众号:前端修炼之路,欢迎关注。

前言

前几日用form表单提交一个留言,发现一个奇怪的问题。

留言板有个来源的字段,用来获取网页的地址。测试时发现在谷歌Chrome浏览器中,可以正确获取到网址来源,然后用火狐Firefox浏览器,却无法正确获取到网址来源。因为后台使用的是PHP,留言成功之后通过JS弹出alert提示框,然后再通过location.href跳转回留言页面。

所以后台就需要准确的获取到留言页面的地址,但是后台并没有正确的获取到留言页面地址。这是为啥呢❓❓❓

Chrome浏览器和Firefox浏览器对比

看了后台获取来源的代码之后,了解到是通过$_SERVER["HTTP_REFERER"] 这个PHP变量获取的。然后就去翻PHP文档,找到了HTTP_REFERER变量的文档说明:

引导用户代理到当前页的前一页的地址(如果存在)。由 user agent 设置决定。并不是所有的用户代理都会设置该项,有的还提供了修改 HTTP_REFERER 的功能。简言之,该值并不可信。

去百度百科里面,又看到如下内容:

HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。

从上面的论述中我们可以得到如下几点结论:

  1. http_referer由浏览器生成,并不是所有浏览器都会设置该值。
  2. http_referer可以伪造,并不可信。

通过谷歌和火狐浏览器自带的调试工具,可以看到HTTP请求头信息

chrome浏览器

firefox浏览器

从上图可以发现,Chrome浏览器中的请求头中的Referer地址为详细的页面地址信息,而Firefox浏览器中的请求头中的Referer地址,却只显示了域名信息。

难道是Firefox浏览器设置的问题吗? 所以我又去Stackoverflow查找了一番。

Stackoverflow

从上图可以得出两个结论:

  1. HTTP_REFERER这个变量真是不可信
  2. Firefox浏览器允许用户修改这个字段

那在Firefox浏览器中怎么修改这个字段呢?

firefox-config

在火狐浏览器中输入about:config,然后搜索network.http.send,找到network.http.senRefererHeader,将这个字段值修改为0,就会禁止浏览器发送refer信息。

HTTP_REFERER的用途

HTTP_REFERER提供了引导用户代理到当前页的前一页的地址信息。

常见的一些应用场景有:

  • 统计文章来源。例如有多少次是来自谷歌搜索结果,多少次来自百度搜索结果等。
  • 图片防盗链。不是自己站点上的访问,图片显示404等。

如果你经常写博客,就一定会遇到盗用你辛辛苦苦整理过的文章不跟你打任何招呼甚至连原文链接都一并抹除的网站,文字这个层面我们没法控制,但是图片这个层面我们是可以控制的。

举个例子,如果你也曾复制过一些类似腾讯等网站的文章,你会发现黏贴下来发表之后经常出现图片无法显示,这是如何做到的呢?

场景:a站点的图片全部存储在c站点(云服务器)上,c站点将识别调用方是否来自a站点,否则显示一张错误图片,b站是盗图网站。a站和b站的代码一致,如下所示:

<img src="http://www.c.com/image.php?fname=jb.png" width="500px" height="500px" />;

重点是c站的代码,如下所示:

<?php
if(strpos($_SERVER['HTTP_REFERER'], 'www.a.com')  !== false){
    //以下的写法并不严谨,这里只是做测试
    if(file_exists($_GET['fname'])){
        echo file_get_contents($_GET['fname']);
    }
}

这样当a站访问时图片可以正常显示,而b站访问时图片是显示不出来的。

PHP $_SERVER['HTTP_REFERER'] 无效

通常下面的一些方式,$_SERVER['HTTP_REFERER'] 会无效:

  1. 直接输入网址访问该网页。
  2. Javascript 打开的网址。
  3. Javascript 重定向(window.location)网址。
  4. 使用 meta refresh 重定向的网址。
  5. 使用 PHP header 重定向的网址。
  6. flash 中的链接。
  7. 浏览器未加设置或被用户修改。

所以一般来说,只有通过 <a></a> 超链接以及 POSTGET 表单访问的页面,$_SERVER['HTTP_REFERER'] 才有效。

结论

遇到的这个问题,本来以为是前端造成,代码哪里有问题,没有给后端发送正确的来源。通过百度和查找PHP手册发现,这个问题只能通过后端PHP修改。

HTTP_REFERER这个变量其实也是HTTP协议中相关知识。然后又因为不同的浏览器客户端对请求头处理规则不一样,所以造成了这个问题。

也因为这个问题,补充了一个知识点,就是图片防盗链的基本原理。所以遇到一个问题后,通过学习可以补充不少相关联的知识点。✌️


本文参考、翻译了以下文章,并进行了整理。

参考链接:


siberiawolf
2.5k 声望853 粉丝

每天多学一点,幸福多攒一点。