目录
一、ngx_http_rewrite_module模块指令
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之一,用于实现URL的重写
URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为自动访问,另外还可以在一定程度上提高网站的安全性
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
前提:关闭所有设备的防火墙和核心防护,以及开启服务器的nginx
[root@localhost ~]#systemctl stop firewalld
[root@localhost ~]#setenforce 0
[root@localhost ~]#systemctl start nginx
1、if指令
1.1 if指令基本语法
用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单次判断,不支持使用if else或者if elif这样的多重判断
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
#用法格式
if (条件匹配) {
action
}
需使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接
字符 | 说明 |
---|---|
= | 比较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false |
!= | 比较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false |
~ | 区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假 |
!~ | 区分大小写字符,判断是否匹配,不满足匹配条件为真,满足匹配条件为假 |
~* | 不区分大小写字符,可以通过正则表达式匹配,满足匹配条件为真,不满足匹配条件为假 |
!~* | 不区分大小字符,判断是否匹配,满足匹配条件为假,不满足匹配条件为真 |
-f 和 !-f | 判断请求的文件是否存在和是否不存在 |
-d 和 !-d | 判断请求的目录是否存在和是否不存在 |
-x 和 !-x | 判断文件是否可执行和是否不可执行 |
-e 和 !-e | 判断请求的文件或目录是否存在和是否不存在(包括文件,目录,软链接) |
注:
①如果$变量的值为空字符串或0,则if指令认为该条件为false,其他条件为true。
②nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
1.2 if指令操作
1.2.1 案例一
要求:判断当前请求的是什么协议?
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server{
listen 80;
server_name www.dh.com;
root /opt/;
location /main {
index index.html;
default_type text/html;
if ( $scheme = http ){
echo "if-----> $scheme";
}
if ( $scheme = https ){
echo "if ----> $scheme";
}
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
1.2.2 案例二
要求:判断当前请求资源文件的磁盘路径是否存在?
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server{
listen 80;
server_name www.dh.com;
root /opt/;
location /main {
index index.html;
default_type text/html;
if ( -f $request_filename ){
echo "$request_filename is exist";
}
if ( !-e $request_filename ){
echo "$request_filename is not exist";
}
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
2、return命令
return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行,return可以在server、if 和 location块进行配置
#格式用法
return code; #返回给客户端指定的HTTP状态码
return code [text]; #返回给客户端的状态码及响应报文的实体内容,可以调用变量,其中text如果有空格,需要用单或双引号
return code url; #返回给客户端的URL地址
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server{
listen 80;
server_name www.dh.com;
root /opt;
location /test {
default_type text/plain;
return 301 http://www.baidu.com;
}
location /main {
index index.html;
default_type text/html;
if (!-e $request_filename){
return 302 /index.html;
}
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
当访问172.16.12.10/test时
当访问172.16.12.10/main时
注:访问的main下的不存在目录
前面的if语句执行后会停止匹配
拓展:状态码301与302的区别
301(永久重定向): 当服务器返回 301 状态码时,表示所请求的资源已被分配了新的 URL。这种重定向是永久性的,浏览器会缓存重定向的信息,下次再访问相同的URL时会直接跳转到新的URL,不再向原URL发送请求
302(临时重定向):当服务器返回 302 状态码时,表示所请求的资源暂时被移动到了另一个位置。这种重定向是临时性的,浏览器会在每次请求时都重新向服务器发出请求,以获取最新的重定向信息
#先关闭nginx服务器
[root@localhost ~]#systemctl stop nginx
客户端测试:
当访问172.16.12.10/test时
当访问172.16.12.10/main时
3、set命令
这个命令通常用于在 Nginx 配置中创建自定义变量,以便在后续配置块中使用。例如,可以使用set
命令来动态地构建一些值,然后在代理、重定向或其他指令中使用这些自定义变量
#格式用法
set $variable value;
#$variable 是要定义或更新的变量名,value 是要分配给变量的值
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
server_name www.dh.com;
root /opt/;
location /mnt {
set $name yun;
echo $name;
set $my_port $server_port; #将内置变量定义给自定义变量
echo $my_port;
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
4、break指令
用于中断当前相同作用域(location)中的其他Nginx配置,与该指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模块中指令就不再执行,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和locationif块中使用
注: break指令在location块中后续指令还会继续执行,只是不执行 ngx_http_rewrite_module 模块的指令,其它指令还会执行
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
server_name www.dh.com;
root /opt/;
location /mnt {
set $name yun;
echo $name;
break;
set $my_port $server_port;
echo $my_port;
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
5、rewrite指令
5.1 rewrite指令基本语法
通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,rewrite主要是针对用户请求的URL或者是URI做具体处理
rewrite可以配置在 server、location、if
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
#格式用法
rewrite regex replacement [flag];
#regex 是一个正则表达式,用于匹配请求的URI
#replacement 是替换字符串,用于替换匹配到的部分
#flag 是可选的标记,用于指定重写规则的行为,如redirect(临时重定向302)、permanent(永久重定向301)、break和las
注:
如果在同一级配置块中存在多个rewrite规则,那么会自上而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的标志位用于控制此循环机制如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向301
5.1.1 regex正则表达式
regex正则表达式 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配任意单个数字 ,即[0-9] |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
* | 匹配重复零次或更多次 |
+ | 匹配重复一次或更多次 |
? | 匹配重复零次或一次 |
{n} | 匹配重复n次 |
{n,} | 匹配重复n次或更多次 |
{n,m} | 匹配重复n到m次 |
*? | 匹配重复任意次,但尽可能少重复 |
+? | 匹配重复1次或更多次,但尽可能少重复 |
?? | 匹配重复0次或1次,但尽可能少重复 |
{n,m}? | 匹配重复n到m次,但尽可能少重复 |
{n,}? | 匹配重复n次以上,但尽可能少重复 |
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^kgc] | 匹配除了kgc 这几个字母以外的任意字符 |
5.1.2 flag可选标记
利用nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型
-
跳转型指由客户端浏览器重新对新地址进行请求
-
代理型是在WEB服务器内部实现跳转
redirect;302
#临时重定向,重写完成后以临时重定向方式。直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;301
#永久重定向,重写完成后以永久重定向方式,直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户301
break与last的区别:
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server{
listen 80;
server_name www.dh.com;
root /mnt/;
location /break {
rewrite .* /test break;
}
location /last {
rewrite .* /test last;
}
location /test {
return 403;
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
5.2 rewrite指令操作
5.2.1 案例一
要求:访问172.16.12.10/hn/会跳转到 172.16.12.10/hainan/
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
server_name www.dh.com;
root /opt/;
location /hn {
rewrite ^/hn/(.*) /hainan/$1 permanent;
}
}
[root@localhost ~]#nginx -s reload
[root@localhost ~]#mkdir /opt/hainan/
[root@localhost ~]#echo "welcome to hainan" > /opt/hainan/index.html
客户端测试:
5.2.2 案例二
要求:跳转整个网站
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
server_name www.dh.com;
root /opt/;
location / {
rewrite / http://www.baidu.com permanent; #如果访问根就跳转到百度
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
用客户端访问,并查看客户端浏览器的开发者工具(按快捷键F12)
5.2.3 案例三
要求:http协议跳转https协议
nginx服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
listen 443 ssl;
root /opt/;
ssl_certificate /opt/ssl/www.kgc.com.crt;
ssl_certificate_key /opt/ssl/www.kgc.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
if ( $scheme = http ) { #如果请求协议是http
rewrite /(.*) https://$host/$1 permanent; #重写成https
}
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
用客户端访问,并查看客户端浏览器的开发者工具(按快捷键F12)
5.2.4 案例四
更换目录访问方式,目录转化为对象存储形式
要求:如何实现下列网页的跳转
/20200106/static->/static?id=20200106
/20200123/image ->/image?id=20200123
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
server_name www.dh.com;
root /opt/;
location /(\d+)/(.+)/ {
rewrite ^/(\d+)/(.+)/ /$2?id=$1 break;
# \d+:一个以上数字; .+:一个以上的字符
}
}
[root@localhost ~]#nginx -s reload
5.2.5 案例五
多目录转换访问方式
要求:如何实现下列网页的跳转
www.dh.com/images/20200106/1.jpg => www.dh.com/index.do?name=images&dir=20200106=&file=1.jpg
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server {
listen 80;
server_name www.dh.com;
root /opt/;
if($host ~* (.*)\.dh\.com) {
rewrite ^/(.*)/(\d+)/(.*)$ /index.do?name=$1&dir=$2&file=$3 last;
}
}
[root@localhost ~]#nginx -s reload
二、防盗链
1、防盗链的概述
防盗链是一种用于保护网站资源不被未经授权的其他网站所引用的技术
在 Nginx 中,可以通过检查 HTTP 请求中的 Referer(引用页)信息来实现防盗链,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是之前的那个网站域名,正常的referer信息有以下几种:
referer信息 | 说明 |
---|---|
none | 请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息 |
blocked | 请求报文有referer首部,但无有效值,比如为空 |
server_names | eferer首部中包含本主机名及即nginx 监听的server_name |
arbitrary_string | 自定义指定字符串,但可使用*作通配符。示例: *.dh.org www.dh.* |
regular expression | 被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.dh\.com |
2、盗链情况
被盗服务器操作:在网页根目录添加图片1.jpg
盗取服务器操作:开启httpd服务,添加web前端配置
[root@localhost ~]#vim /var/www/html/index.html
<html>
<body>
<h1>Hello World </h1>
<img src="http://172.16.12.10/1.jpg"/>
</body>
</html>
[root@localhost html]#systemctl restart httpd
客户端测试:访问盗取服务器的网页,可以直接获得被盗服务器图片
3、实现防盗链操作
防盗服务器配置:
[root@localhost ~]#vim /apps/nginx/conf.d/dh.conf
server{
listen 80;
server_name www.dh.com;
location ~* \.(jpg|gif|swf)$ {
root /opt/;
valid_referers none blocked *.dh.com dh.com;
if ( $invalid_referer ) {
return 403;
}
}
}
[root@localhost ~]#nginx -s reload
客户端测试:
访问盗取服务器的网页,盗取服务器不能再盗取图片,并返回状态码403(请求被禁止)
客户端也可以设置非法访问所访问到的图片: