博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTTP 笔记与总结(6)referer 头与防盗链
阅读量:5105 次
发布时间:2019-06-13

本文共 4486 字,大约阅读时间需要 14 分钟。

在百度贴吧(或 QQ 空间等)中找到一张图片,复制图片地址,在站外通过 img src 引用,会发现:

 

此外,在一些统计软件中,统计访客的来路(直接访问、外部链接、搜索引擎),都用到了 HTTP 协议请求头中 Referer 的知识。

 

 

【例】直接访问 www.baidu.com 和 在通过本地页面跳转至 www.baidu.com,观察 HTTP 请求头信息的差异:

① 直接访问百度,HTTP 请求头信息:

 

② 通过本地 referer.html 跳转至 www.baidu.com:

 

HTTP 协议头信息的 Referer 选项代表网页的来源(上一页的地址),如果是直接访问(直接在浏览器输入地址访问),则没有 Referer 选项。

 

 

配置 Apache 服务器用于图片防盗链

原理:在 web 服务器层面,根据 http 协议的 referer 头信息来判断网页来源,如果来自站外,则统一重写到一个很小的防盗链题型图片上(URL 重写)。

步骤:

① 打开 apache 重写模块 rewrite_mod。重启 apache。

 

② 在需要防盗链的网站或目录下,写 .htaccess 文件,并指定防盗链规则 —— 分析 referer,如果不是来自本站,则重写

例如在 127.0.0.17/php/http/ 目录下新建 .htaccess 文件,写入重写规则:

当是 jpg/jpeg/gif/png 图片 ,且 referer 头与 127.0.0.17 不匹配时重写,统一 Rewrite 到某个防盗链图片

重写方式参见:

D:\practise\php\http\.htaccess:

RewriteEngine OnRewriteCond %{REQUEST_FILENAME} .*\.(jpg|jpeg|gif|png) [NC]RewriteCond %{HTTP_REFERER} !127.0.0.17 [NC]RewriteRule .* http://127.0.0.17/php/logo.jpg

第 1 行:开启重写功能;

第 2 行:当请求的文件名以 .jpg,.jpeg,.gif,.png 结尾时

第 3 行:当 HTTP 的 Referer 头 与 服务器地址 127.0.0.17 不匹配时

第 4 行:重写规则,把符合条件的文件重写到 http://127.0.0.17/php/http/logo.jpg 上

 

实例:

D:\practise\php\logo.jpg:

 

D:\practise\php\http\a.jpg:

 

站内地址(127.0.0.17,D:\practise),站外地址(127.0.0.16,D:\practise\php)。也就是说,127.0.0.16 上的文件外链 127.0.0.17 上的 a.jpg 时,会被重写至 logo.jpg。

http://127.0.0.17/php/http/referer.html:

	
Document

输出:

  

 

http://127.0.0.16/http/referer.html:

	
Document

输出:

 

防盗链功能实现。

 

如果把 .htaccess 放在根目录,则网站所有的图片都会受到影响;如果只要对某个目录生效,则在 .htaccess 中加上:

Rewrite Base /php/http

 

 

采集图片功能(通过设置 Referer 头信息,绕过防盗链)

先测试通过 HTTP GET 请求图片

caiji.php:

get();

输出:

  

 

修改 http.class.php line:72(增加判断 $url['query'],防止出现 Notice 级别的错误):

1 
conn($url); 46 $this->setHeader('Host:' . $this->url['host']); 47 } 48 49 //写请求行 50 protected function setLine($method){ 51 $this->line[0] = $method . ' ' . $this->url['path'] . '?' . $this->url['query'] . ' ' . $this->version; 52 } 53 54 //写头信息 55 public function setHeader($headerline){ 56 $this->header[] = $headerline; 57 } 58 59 //写主体信息 60 protected function setBody($body){ 61 //构造 body 的字符串 62 $this->body[] = http_build_query($body); 63 } 64 65 //连接 url 66 public function conn($url){ 67 $this->url = parse_url($url); 68 //判断端口 69 if(!isset($this->url['port'])){ 70 $this->url['port'] = 80; 71 } 72 //判断 query 73 if(!isset($this->url['query'])){ 74 $this->url['query'] = ''; 75 } 76 $this->fh = fsockopen($this->url['host'], $this->url['port'], $this->errno, $this->errstr, 3); 77 } 78 79 //构造 GET 请求的数据 80 public function get(){ 81 $this->setLine('GET'); 82 //发送请求 83 $this->request(); 84 return $this->response; 85 } 86 87 //构造 POST 请求的数据 88 public function post($body = array()){ 89 //构造请求行 90 $this->setLine('POST'); 91 92 //设置 Content-type 和 Content-length 93 $this->setHeader('Content-type: application/x-www-form-urlencoded'); 94 95 //构造主体信息, 和 GET 请求不一样的地方 96 $this->setBody($body); 97 98 $this->setHeader('Content-length: ' . strlen($this->body[0])); 99 100 //发送请求101 $this->request();102 return $this->response; 103 }104 105 //发送请求106 public function request(){107 //把请求行、头信息、主体信息拼接起来108 $req = array_merge($this->line, $this->header, array(''), $this->body, array(''));109 $req = implode(self::CRLF, $req);110 //echo $req;exit;111 112 fwrite($this->fh, $req);113 114 while(!feof($this->fh)){115 $this->response .= fread($this->fh, 1024);116 }117 118 //关闭连接119 $this->close();120 }121 122 //关闭连接123 public function close(){124 fclose($this->fh);125 }126 }
View Code

 

测试防盗链:

caiji.php

1 
get(); 7 8 //取出 图片二进制码(和 HTTP 头信息中间有一个空行 \r\n,加上空行之前的换行\r\n,一共4个字节) 9 $res = file_put_contents('./b.jpg', substr(strstr($res, "\r\n\r\n"), 4));10 echo 'complete';

运行之后,因为没有 Referer 头信息,因此被认为是盗链,生成的 b.jpg 变成了 “不要盗链”:

 

 

在 caiji.php 中加入 Referer 头信息后:

caiji.php

1 
setHeader('Referer:127.0.0.17'); 6 $res = $http->get(); 7 8 //取出 图片二进制码(和 HTTP 头信息中间有一个空行 \r\n,加上空行之前的换行\r\n,一共4个字节) 9 $res = file_put_contents('./b.jpg', substr(strstr($res, "\r\n\r\n"), 4));10 echo 'complete';

 

此时采集到的 b.jpg 绕过了防盗链正常的显示了:

 

 

待完善:应该判断 response 的 MIME 头信息,确定图片的类型,再把文件写入相应类型的文件中。  

 

转载于:https://www.cnblogs.com/dee0912/p/4646739.html

你可能感兴趣的文章
Mysql 索引优化 - 1
查看>>
LeetCode(3) || Median of Two Sorted Arrays
查看>>
大话文本检测经典模型:EAST
查看>>
linux基础命令-chgrp/chown/chomd
查看>>
待整理
查看>>
一次动态sql查询订单数据的设计
查看>>
C# 类(10) 抽象类.
查看>>
Nginx+Keepalived 实现双击热备及负载均衡
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
jvm参数
查看>>
Something-Summary
查看>>
Spring学习笔记
查看>>
6个有用的MySQL语句
查看>>
我对前端MVC的理解
查看>>
Silverlight实用窍门系列:19.Silverlight调用webservice上传多个文件【附带源码实例】...
查看>>
2016.3.31考试心得
查看>>
mmap和MappedByteBuffer
查看>>
Linux的基本操作
查看>>
转-求解最大连续子数组的算法
查看>>
算法为啥子那么难【转】
查看>>