Rewrite
Rewrite和apache等web服务软件一样,rewrite的主要功能是实现URL地址的重定向。Nginx的rewrite功能需要PCRE软件的支持,即通过perl兼容正则表达式语句进行规则匹配的。默认参数编译nginx就会支持rewrite的模块,但是也必须要PCRE的支持
Rewirte功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。
Rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递参数外的字符串起作用。例如http://www.haha.com/abc/aa/index.php?a=1&b=2 只对/abc/aa/index.php重写
URL:就是具体路径/位置
URI:指的是一个拥有相同类型/特性的对象集合
Nginx:通过ngx_http_rewrite_module模块支持URL重写,支持if条件判断,但不支持else。
跳转:从一个location跳转到另一个location,循环最多可以执行10次,超过后nginx将返回500错误。
PCRE支持:perl兼容正则表达式的语法规则匹配
重写模块set指令:创建新的变量并设其值
语法格式:
rewrite <regex> <replacement> [flag];
regex:表示正则匹配规则
replacement:表示跳转后的内容
flag:表示rewrite支持的flag标记
flag标记说明:
last:本条规则匹配完成后,继续向下匹配新的location URL规则,一般用在server和if中。
break:本条规则匹配完成即终止,不在匹配后面的任何规则,一般使用在location中。
redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。
匹配正则的标识符和意义
^ 必须以^后的实体开头
$ 必须以$前的实体结尾
. 匹配任意单个字符
[] 匹配指定字符集的任意字符
[^] 匹配任何不包括在指定字符集内的任意字符串
| 匹配|之前或之后的实体
() 分组,组成一组用于匹配的实体,通常会有|来协助
\ 转义
* 匹配前面的字符出现零次或者多次,如“ab*”能匹配a、ab、abb
+ 匹配前面的字符出现一次或者多次,如“ab+”能匹配ab、abb,但是不能匹配a
? 匹配前面的字符出现零次或者一次,如“ab(cd)?”能匹配ab、abcd
(pattern) 匹配括号内pattern并可以在后面获取对应的匹配,常用$0-$9属性获取小括号中匹配的内容。如^(hello | chenyu)$ //字符串为“hello chenyu”,可以捕获的结果为: $1=hello$2=chenyu 这些被捕获的数据,在后面就可以当作变量一样进行使用了
nginx的rewrite功能在企业里应用非常广泛
- 可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求
- 为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态的URL地址伪装成静态地址提供服务
- 网址更新域名后,让旧的访问跳转到新的域名上,例如访问京东的360buy.com会跳转到jd.com
- 根据特殊变量、目录、客户端的信息进行URL调整等。
rewrite配置
nginx访问自定义网页
[root@nginx html]# ls
404.html 50x.html index.html nginx-logo.png poweredby.png
[root@nginx html]# mkdir haha
[root@nginx html]# cd haha/
[root@nginx haha]# ls
hehe.jpg
[root@nginx haha]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
}
[root@nginx haha]# nginx -s reload
浏览器访问
flag标记–break
[root@nginx html]# ls
404.html 50x.html haha index.html nginx-logo.png poweredby.png
[root@nginx html]# mv haha/ niuma
再次访问会发现404找不到网页
需要写rewrite
[root@nginx niuma]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
rewrite ^/imgs/(.*\.jpg)$ /niuma/$1 break;
}
[root@nginx niuma]# nginx -s reload
再次浏览器访问访问,路径不变http://192.168.40.99/haha/hehe.jpg
还可以使用break,让我们访问得站点跳转到百度得首页
[root@nginx html]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
rewrite ^/haha/(.*\.jpg)$ http://www.baidu.com break;
}
浏览器访问http://192.168.40.99/haha/hehe.jpg
flag标记-last
[root@nginx niuma]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
rewrite ^/haha/(.*\.jpg)$ /niuma/$1 last;
}
[root@nginx niuma]# nginx -s reload
rewrite中flag标记last实现2次重写后,重定向到百度的站点http://www.baidu.com
[root@nginx niuma]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
rewrite ^/haha/(.*\.jpg)$ /niuma/$1 last;
}
location /niuma {
rewrite ^/niuma/(.*\.jpg)$ http://www.baidu.com last;
}
[root@nginx niuma]# nginx -s reload
浏览器访问http://192.168.40.99/haha/hehe.jpg
flag标记–redirect
[root@nginx niuma]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
rewrite ^/haha/(.*\.jpg)$ /niuma/$1 redirect;
}
[root@nginx niuma]# nginx -s reload
浏览器访问http://192.168.40.99/haha/hehe.jpg
flag标记–permanent
[root@nginx niuma]# vim /usr/local/nginx/conf/nginx.conf
location /haha {
rewrite ^/haha/(.*\.jpg)$ /niuma/$1 permanent;
}
[root@nginx niuma]# nginx -s reload
浏览器访问http://192.168.40.99/haha/hehe.jpg
配置基于域名跳转
现在公司旧的域名www.haha1.com有业务需求,需要使用新的域名www.haha.com代替,
但是旧域名不能废除,需要跳转到新的域名上,而且后面的参数保持不变
修改nginx服务器主机名为www.haha1.com
[root@nginx html]# hostnamectl set-hostname www.haha1.com
[root@nginx html]# bash
[root@www html]#
将两个域名写入到/etc/hosts中,并传给客户端
[root@www html]# vim /etc/hosts
192.168.40.99 www.haha1.com
192.168.40.99 www.haha.com
[root@www html]# scp /etc/hosts root@192.168.40.100:/etc/hosts
root@192.168.40.100's password:
hosts 100% 216 100.5KB/s 00:00
修改配置文件,写入rewrite和if结合使用
server {
listen 80;
server_name www.haha1.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
if ($host = 'www.haha1.com') { //变量host为rewrite的全局变量
rewrite ^/(.*)$ http://www.haha.com/$1 permanent;
} //$1是匹配http://www.haha.com/后面的字段
root html;
index index.html index.htm;
}
[root@www html]# echo "niuma test" > /usr/local/nginx/html/index.html
[root@www html]# nginx -s reload
客户端使用浏览器访问–http://www.haha1.com—我们会发现自动跳转到新的域名www.haha.com中
配置基于客户端ip访问跳转
假如今天公司业务新版本上线,要求所有ip访问任何内容都显示一个固定维护页面,
只有公司ip:192.168.40.100访问正常
[root@www html]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.haha1.com;
set $rewrite true;
if ($remote_addr = "192.168.40.100") {
set $rewrite false;
}
if ($rewrite = true) {
rewrite (.+) /weihu.html;
}
location = /weihu.html {
root /var/www/html;
}
location / {
root html;
index index.html index.htm;
}
新建/var/www/html目录,并往该目录下写入文件weihu.html,内容为weihu
[root@www html]# mkdir /var/www/html -p
[root@www html]# echo "weihu" > /var/www/html/weihu.html
[root@www html]# nginx -s reload
//将nginx服务器的/etc/hosts文件发送给客户端2(192.168.40.101)
[root@www html]# scp /etc/hosts root@192.168.40.101:/etc/hosts
验证
进入客户端1(192.168.40.100),访问http://www.haha1.com
进入客户端2(192.168.40.101),访问http://www.haha1.com
配置基于浏览器分离–firefox和chrome浏览器
在/usr/local/nginx/html目录中创建如下目录和文件
[root@www html]# mkdir firefox chrome
[root@www html]# echo "firefox test" > firefox/index.html
[root@www html]# echo "chrome test" > chrome/index.html
修改配置文件
[root@www html]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
if ($http_user_agent ~ Firefox) {
rewrite ^(.*)$ /firefox/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
root html;
index index.html index.htm;
}
location /firefox {
root html;
index index.html;
}
location /chrome {
root html;
index index.html;
}
使用nginx -t 测试配置文件是否正确
[root@www html]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
重载nginx
[root@www html]# nginx -s reload
验证
1、chrome谷歌浏览器访问
2、Firefox浏览器访问
配置防盗链
防盗链案例
了解防盗链的原理之前,我们得先学习一个HTTP的头信息Referer,当浏览器向web服务器发送请求的时候,一般都会带上Referer,来告诉浏览器该网页是从哪个页面链接过来的。
后台服务器可以根据获取到的这个Referer信息来判断是否为自己信任的网站地址,如果是则放行继续访问,如果不是则可以返回403(服务端拒绝访问)的状态信息。
语法:
valid_referers none blocked server_names string
none: 如果Header中的Referer为空,允许访问
blocked:在Header中的Referer不为空,但是该值被防火墙或代理进行伪装过,如不带"http://" 、"https://"等协议头的资源允许访问。
server_names:指定具体的域名或者IP
string: 可以支持正则表达式和*的字符串。如果是正则表达式,需要以~开头表示
案例
在/usr/local/nginx/html目录下创建abc目录,并上次一张图片到该目录下
[root@www html]# cd /usr/local/nginx/html/
[root@www html]# mkdir abc
[root@www html]# cd abc/
[root@www abc]# cp /usr/local/nginx/html/niuma/hehe.jpg .
[root@www abc]# ls
hehe.jpg
配置nginx配置文件
[root@www abc]# vim /usr/local/nginx/conf/nginx.conf
location ~* \.(jpg|png) {
root html/abc;
}
[root@www abc]# nginx -s reload
浏览器可以正常访问
使用命令查看referer信息,此时还未配置防盗链
[root@www abc]# curl --referer http://baidu.com -I http://192.168.40.99/hehe.jpg
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Fri, 14 Oct 2022 08:41:12 GMT
Content-Type: image/jpeg
Content-Length: 503539
Last-Modified: Fri, 14 Oct 2022 08:37:20 GMT
Connection: keep-alive
ETag: "63491fc0-7aef3"
Accept-Ranges: bytes
开始配置防盗链
[root@www abc]# vim /usr/local/nginx/conf/nginx.conf
location ~* \.(jpg|png) {
root html/abc;
}
valid_referers none blocked www.haha1.com; //有效的来源
if ($invalid_referer) { //无效的来源
return 403;
break;
}
[root@www abc]# nginx -s reload
再次使用浏览器访问,我们发现是可以访问的
但是使用命令查看referer信息的时候,会发现返回了403了
[root@www abc]# curl --referer http://baidu.com -I http://192.168.40.99/hehe.jpg
HTTP/1.1 403 Forbidden
Server: nginx/1.22.0
Date: Fri, 14 Oct 2022 08:45:04 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
那么此时防盗链已经做好了