.图片防盗链模块详解

 

图片防盗链不需要程序配合,根据图片来源来实现,但是只能先限制基本的图片盗用,无法防止图片采集.

 

1.referer模块简介

nginx模块ngx_http_referer_module通常用于阻挡来源非法的域名请求.我们应该牢记,伪装Referer头部是非常简单的事情,所以这个模块只能用于阻止大部分非法请求.我们应该记住,有些合法的请求是不会带referer来源头部的,所以有时候不要拒绝来源头部(referer)为空的请求.

 

2.防盗链模块指令

referer_hash_bucket_size

语法:
Syntax:     referer_hash_bucket_sizesize;
默认值为64:
Default:   referer_hash_bucket_size64;
配置段:
Context:  server,location
第一次出现是nginx版本1.0.5:
This directive appeared in version 1.0.5.

 

referer_hash_max_size

语法:
Syntax:     referer_hash_max_sizesize;
默认值2048k:
Default:   referer_hash_max_size2048;
配置段:
Context:  server,location
第一次出现是nginx版本1.0.5:
This directive appeared in version 1.0.5.

 

valid_referers

语法:
Syntax:     valid_referersnone | blocked | server_names | string ...;
默认值:
Default:   —
配置段:
Context:  server,location

 

指定合法的来源’referer, 他决定了内置变量$invalid_referer的值,如果referer头部包含在这个合法网址里面,这个变量被设置为0,否则设置为1.记住,不区分大小写的.

 

none               #“Referer” 来源头部为空的情况;从浏览器输入的。
blocked            #“Referer” 来源头部不为空,但是里面的值被代理或者防火墙删除了,这些值都不以http://或者https://开头.
server_names       #“Referer”来源头部包含当前的server_names(当前域名)
arbitrary string   #任意字符串,定义服务器名或者可选的URI前缀.主机名可以使用*开头或者结尾,在检测来源头部这个过程中,来源域名中的主机端口将会被忽略掉
regular expression #正则表达式,~表示排除https://或http://开头的字符串.

 

图片使用来源头部做防盗链是最合理的. 简单、实用。但是没有办法防采集。

 

3.实例:

location ~* \.(gif|jpg|png|bmp)$ {
   valid_referers none blocked *.stu31.com server_names ~\.google\.~\.baidu\.;
   if ($invalid_referer) {
       return 403;
       
#rewrite ^/ http://www.stu31.com/403.jpg;
    }
}

 

实例详解:

以上所有来至用户输入,stu31.com和域名中包含googlebaidu的站点都可以访问到当前站点的图片,如果来源域名不在这个列表中,那么$invalid_referer等于1,在if语句中返回一个403用户,这样用户便会看到一个403的页面,如果使用下面的rewrite,那么盗链的图片都会显示403.jpg。如果用户直接在浏览器输入你的图片地址,那么图片显示正常,因为它符合none这个规则


.

.重写模块详解

 

1重写模块介绍

Rewrite 主要的功能就是实现URL的重写,NginxRewrite规则采用Pcreperl兼容正则表达式的语法规则匹配,如果需要NginxRewrite功能,在编译Nginx之前,需要编译安装PCRE库。根据相关变量重定向和选择不同的配置,从一个location跳转到另一个location,不过这样的循环最多可以执行10次,超过后nginx将返回500错误。同时,重写模块包含set指令,来创建新的变量并设其值,这在有些情景下非常有用的,如记录条件标识、传递参数到其他location、记录做了什么等等。

 

2.重写模块指令

break指令:

语法:
Syntax:     break;
默认值:
Default:   —
应用配置段:
Context:  server,location, if

完成当前设置的重写规则,停止执行其他的重写规则。

 

if指令:

语法:
Syntax:     if(condition) { ... }
默认值:
Default:   —
应用配置段:
Context:  server,location

注意:尽量考虑使用try_files代替。

 

判断的条件:

(1). 一个变量的名称:空字符传”“或者一些“0”开始的字符串为false。
(2). 字符串比较:使用=或!=运算符
(3). 正则表达式匹配:使用~(区分大小写)和~*(不区分大小写),取反运算!~和!~*。
(4). 文件是否存在:使用-f和!-f操作符
(5). 目录是否存在:使用-d和!-d操作符
(7). 文件、目录、符号链接是否存在:使用-e和!-e操作符
(8). 文件是否可执行:使用-x和!-x操作符


 

 

return指令:

语法:
Syntax:     returncode [text];
            returncode URL;
            returnURL;
默认值:
Default:   —
应用配置段:
Context:  server,location, if

 

停止处理并为客户端返回状态码。非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204400402-406408410, 411, 413, 416500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头补值。没有状态码的URL将被视为一个302状态码。

 

rewrite指令:

语法:
Syntax:     rewriteregex replacement [flag];
默认值:
Default:   —
应用配置段:
Context:  server,location, if

 

按照相关的正则表达式与字符串修改URI,指令按照在配置文件中出现的顺序执行。可以在重写指令后面添加标记。

 

注意:如果替换的字符串以http://开头,请求将被重定向,并且不再执行多余的rewrite指令。

尾部的标记(flag)可以是以下的值

last      #停止处理重写模块指令,之后搜索location与更改后的URI匹配。
break     #完成重写指令。
redirect  #返回302临时重定向,如果替换字段用http://开头则被使用。
permanent #返回301永久重定向。


 

last详解:

解决死循环,对当前请求的处理检查URL重写规则,如果匹配规则需要被重写,服务器对后续规则无需再检查,让客户端将新的重写请求发送给服务器,服务器重新发起检查,这次检查会重头到尾检查一遍。

 

如果没用last

一个location中多条URL重写规则,对请求的处理会检查规则,匹配到后发现需要重写,服务器会通知客户端请求需要重写,客户端就重新发重写过后的请求到服务器,服务器对新的重写好的请求还是需要检查规则,如果检查到匹配某条规则后就又需要重写,客户端就又要发送新的重写请求到服务器,形成循环重写了。

 

break详解:

客户端发送请求URL到服务器,服务器发现其需要匹配URL重写规则,服务器通知客户端请求需要重写,客户端就将重写过的请求URL发送给服务器,服务器不再检查URL重写规则,直接响应。

 

rewrite_log指令:

语法:
Syntax:     rewrite_logon | off;
默认值:
Default:   rewrite_logoff;
应用配置段:
Context:  http,server, location, if
变量:无


启用时将在error log中记录notice级别的重写日志。

 

set指令:

语法:
Syntax:     set$variable value;
默认值:
Default:   —
应用配置段:
Context:  server,location, if

为给定的变量设置一个特定值。

 

uninitialized_variable_warn指令:

语法:
Syntax:     uninitialized_variable_warnon | off;
默认值:
Default:   uninitialized_variable_warnon;
应用配置段:
Context:  http,server, location, if

控制是否记录未初始化变量的警告信息。

 

3.官方实例:

server {
   ...
   rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
   rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
   return  403;
   ...
}

 

解释:

如果访问URIdownload开头后面跟任意内容,后跟media下跟一个任意名称的以.结尾的所有内容都替换成为download开头后面跟任意内容,把media替换成mp3下跟任意名称以.mp3结尾的内容了,实现了后向引用

 

.URL重写实验

 

1.存在一个虚拟主机bbs.stu31.com

 

[root@www ~]# vim/etc/nginx/extra/nginx-vhost.conf
server {
       listen 80;
       server_name bbs.stu31.com;
       index index.html index.htm;
       root /www/vhosts/bbs.stu31.com;
       access_log/var/log/nginx/bbs.stu31.com-access.log main;
       location / {
 
       }
}

 

2.网站测试页:

[root@www ~]# cat/www/vhosts/bbs.stu31.com/index.html
Welconf to bbs.stu31.com

                                

 

3.访问测试正常:

[root@www ~]# curl http://bbs.stu31.com
Welconf to bbs.stu31.com

 

4.如果bbs网站下存在一个特定p_w_picpaths目录,存放一些图片,我就只设置一个测试页吧!

[root@www ~]# mkdir/www/vhosts/bbs.stu31.com/p_w_picpaths
[root@www ~]# echo "this is the p_w_picpathssite" >/www/vhosts/bbs.stu31.com/p_w_picpaths/index.html

 

6.我们将p_w_picpaths这个目录永久移动到pictures目录

[root@www ~]# mv/www/vhosts/bbs.stu31.com/p_w_picpaths/ /www/vhosts/bbs.stu31.com/pictures

 

现在访问原来的bbs.stu31.com就会失败;

[root@www ~]# curlhttp://bbs.stu31.com/p_w_picpaths
<html>
<head><title>404 NotFound</title></head>
<body bgcolor="white">
<center><h1>404 NotFound</h1></center>
<hr><center>nginx/1.6.2</center>
</body>
</html>

 

7.我们配置虚拟主机配置文件进行URL重写,访问bbs.stu31.com/p_w_picpaths会自动跳转到我们移动的目录pictures

[root@www ~]# vim/etc/nginx/extra/nginx-vhost.conf
server {
       listen 80;
       server_name bbs.stu31.com;
       index index.html index.htm;
       root /www/vhosts/bbs.stu31.com;
       access_log /var/log/nginx/bbs.stu31.com-access.log main;
       location / {
                rewrite ^/p_w_picpaths/(.*)/pictures/$1;
       }
}

 

8.重启nginx服务:

[root@www ~]# service nginx reload           
nginx: the configuration file/etc/nginx/nginx.conf syntax is ok
nginx: configuration file/etc/nginx/nginx.conf test is successful
Reloading nginx:

                                   [ OK  ]

 

9.访问测试:

wKiom1SfhXLyTGMSAAINXKJWiYA964.jpg

 


10.我们这里的标志位flag省略了,我们来配置一个标志位测试一下:

设置标志位flagrediect;这里是临时重定向到pictures目录

rewrite ^/p_w_picpaths/(.*) /pictures/$1 redirect;

语法检查,重载服务:

[root@www ~]# nginx -t
nginx: the configuration file/etc/nginx/nginx.conf syntax is ok
nginx: configuration file/etc/nginx/nginx.conf test is successful
[root@www ~]# service nginx reload
nginx: the configuration file/etc/nginx/nginx.conf syntax is ok
nginx: configuration file/etc/nginx/nginx.conf test is successful
Reloading nginx:                                          [  OK  ]

 

测试访问

我们这里访问p_w_picpaths服务器响应成302状态,需要客户端重新发送请求URL去访问pictures这个新网站目录:

wKioL1Sfhj2QJoH_AAG-w_zW8qk055.jpg

 

如果设置标志位flaglast

rewrite ^/p_w_picpaths/(.*) /pictures/$1 last;

浏览器访问:http://bbs.stu31.com/p_w_picpaths/

wKiom1SfhafwhErdAAHJe_AOvVs914.jpg

 

如果标志位是permanent;就是被永久重定向了,状态码301

rewrite ^/p_w_picpaths/(.*) /pictures/$1permanent;

浏览器访问:http://bbs.stu31.com/p_w_picpaths/

wKioL1SfhmiRb9XbAAFWYu2Wz2s677.jpg



待续!!!!