Nginx Rewrite相关功能
发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,Nginx服务器利⽤ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regularexpression),因此编
千家信息网最后更新 2025年01月23日Nginx Rewrite相关功能
Nginx服务器利⽤ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regularexpression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之⼀,⽤于实现URL的重写,URL的重写是⾮常有⽤的功能,⽐如它可以在我们改变⽹站结构之后,不需要客⼾端修改原来的书签,也⽆需其他⽹站修改我们的链接,就可以设置为访问,另外还可以在⼀定程度上提⾼⽹站的安全性。
1 ngx_http_rewrite_module模块指令
官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
1.1 if指令
# ⽤于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进⾏配置,Nginx的if语法仅能使⽤if做单次判断,不⽀持使⽤if else或者if elif这样的多重判断,⽤法如下:if (条件匹配) { action}# 使⽤正则表达式对变量进⾏匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使⽤以下符号链接:= #⽐较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false。!= #⽐较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false。~ #表⽰在匹配过程中区分⼤⼩写字符,(可以通过正则表达式匹配),满⾜匹配条件为真,不满⾜为假。!~ #为区分⼤⼩写字符且匹配结果不匹配,不满⾜为真,满⾜为假。~* #表⽰在匹配过程中不区分⼤⼩写字符,(可以通过正则表达式匹配),满⾜匹配条件为真,不满⾜为假。!~* #为不区分⼤⼩字符且匹配结果不匹配,满⾜为假,不满⾜为真。-f 和 ! -f #判断请求的⽂件是否存在和是否不存在-d 和 ! -d #判断请求的⽬录是否存在和是否不存在。-x 和 ! -x #判断⽂件是否可执⾏和是否不可执⾏。-e 和 ! -e #判断请求的⽂件或⽬录是否存在和是否不存在(包括⽂件,⽬录,软链接)。# 示例[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; listen 443 ssl; ssl_certificate /apps/nginx/certs/www.hechunping.tech.crt; ssl_certificate_key /apps/nginx/certs/www.hechunping.tech.key; server_name www.hechunping.tech; location /pc { root html; index index.html; if ( $scheme = http ) { # 如果请求使用的是http协议,则输出scheme is http echo "scheme is $scheme"; } if ( $scheme = https ) { # 如果请求使用的是https协议,则输出scheme is https echo "scheme is $scheme"; } if ( !-f $request_filename ) { # 如果当前请求的资源文件的路径不存在,则输出file is not exist echo "file is not exist"; } }}[root@CentOS7-01 ~]#ls /apps/nginx/html/pc/index.html[root@CentOS7-01 ~]#curl http://www.hechunping.tech/pc/index.htmlscheme is http[root@CentOS7-01 ~]#curl -k /apps/nginx/certs/www.hechunping.tech.key https://www.hechunping.tech/pc/index.htmlcurl: (3) malformedscheme is https[root@CentOS7-01 ~]#curl http://www.hechunping.tech/pc/index111.htmlfile is not exist注: 如果$变量的值为空字符串或是以0开头的任意字符串,则if指令认为该条件为false,其他条件为true。
1.2 set指令
指定key并给其定义⼀个变量,变量可以调⽤Nginx内置变量赋值给key,另外set定义格式为set $key $value,则⽆论是key还是value都要加$符号。# 示例[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location /pc { set $name hechunping; echo $name; set $port $server_port; echo $port; }}[root@CentOS7-01 ~]#curl http://www.hechunping.tech/pchechunping80
1.3 break指令
⽤于中断当前相同作⽤域(location)中的其他Nginx配置,与该指令处于同⼀作⽤域的Nginx配置中,位于它前⾯的配置⽣效,位于后⾯的指令配置就不再⽣效了,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上⼀层作⽤域继续向下读取配置,该指令可以在server块和location块以及if块中使⽤,使⽤语法如下:[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location /pc { set $name hechunping; echo $name; break; #这个示例中,只会echo $name变量的值,因为它在break的前面 set $port $server_port; echo $port; }}[root@CentOS7-01 ~]#curl http://www.hechunping.tech/pchechunping
1.4 return指令
从nginx版本0.8.2开始⽀持,return⽤于完成对请求的处理,并直接向客⼾端返回响应状态码,⽐如其可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提⽰⽂本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执⾏,return可以在server、if和location块进⾏配置,⽤法如下:return code; #返回给客⼾端指定的HTTP状态码return code (text); #返回给客⼾端的状态码及响应体内容,可以调⽤变量return code URL; #返回给客⼾端的URL地址# 示例,80端口跳转https[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; return 301 https://$host$request_uri;}server { listen 443 ssl; server_name www.hechunping.tech; ssl_certificate /apps/nginx/certs/www.hechunping.tech.crt; ssl_certificate_key /apps/nginx/certs/www.hechunping.tech.key;}[root@CentOS7-01 ~]#systemctl reload nginx[root@CentOS7-01 ~]#curl --head http://www.hechunping.techHTTP/1.1 301 Moved PermanentlyServer: HCPWS/1.1Date: Mon, 06 Jan 2020 12:27:18 GMTContent-Type: text/htmlContent-Length: 162Connection: keep-aliveKeep-Alive: timeout=65Location: https://www.hechunping.tech/#注:如果return后面还有指令,将不被执行
1.5 rewrite_log指令
设置是否开启记录ngx_http_rewrite_module模块⽇志记录到error_log⽇志⽂件当中,可以配置在http、server、location或if当中,需要⽇志级别为notice 。# 示例error_log logs/error.log notice; # 主配置文件中修改即可[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location /pc { root html; index index.html; rewrite_log on; rewrite ^(.*)$ https://www.baidu.com$1; }}[root@CentOS7-01 ~]#systemctl reload nginx[root@CentOS7-01 ~]#curl http://www.hechunping.tech/pc302 Found 302 Found
nginx [root@CentOS7-01 ~]#tail -n1 -f /apps/nginx/logs/error.log2020/01/06 20:53:01 [notice] 3274#0: *5 rewritten redirect: "https://www.baidu.com/pc", client: 127.0.0.1, server: www.hechunping.tech, request: "GET /pc HTTP/1.1", host: "www.hechunping.tech"
2 rewrite指令
通过正则表达式的匹配来改变URI,可以同时存在⼀个或多个指令,按照顺序依次对URI进⾏匹配,rewrite主要是针对⽤⼾请求的URL或者是URI做具体处理,以下是URL和URI的具体介绍:URI(universal resource identifier):通⽤资源标识符,标识⼀个资源的路径,可以不带协议。URL(uniform resource location):统⼀资源定位符,是⽤于在Internet中描述资源的字符串,是URI的⼦集,主要包括传输协议(scheme)、主机(IP、端⼝号或者域名)和资源具体地址(⽬录和⽂件名)等三部分,⼀般格式为scheme://主机名[:端⼝号][/资源路径],如:http://www.a.com:8080/path/file/index.html就是⼀个URL路径,URL必须带访问协议。每个URL都是⼀个URI,但是URI不都是URL。例如:http://example.org:8080/path/to/resource.txt #URI/URLftp://example.org/resource.txt #URI/URL/absolute/path/to/resource.txt #URIrewrite的官⽅介绍地址:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite, rewrite可以配置在server、location、if,其具体使⽤⽅式为:rewrite regex replacement [flag];rewrite将⽤⼾请求的URI基于regex所描述的模式进⾏检查,匹配到时将其替换为表达式指定的新的URI。 注意:如果在同⼀级配置块中存在多个rewrite规则,那么会⾃下⽽下逐个检查;被某条件规则替换完成后,会重新⼀轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提⽰500响应码,[flag]所表⽰的标志位⽤于控制此循环机制,如果替换后的URL是以http://或https://开头,则替换结果会直接以重向返回给客⼾端, 即永久重定向301
2.1 rewrite flag使⽤介绍
利⽤nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是redirect(临时重定向)、permanent(永久重定向)、break和last。其中前两种是跳转型的flag,后两种是代理型,跳转型是指有客⼾端浏览器重新对新地址进⾏请求,代理型是在WEB服务器内部实现跳转的。Syntax: rewrite regex replacement [flag]; #通过正则表达式处理⽤⼾请求并返回替换后的数据包。 Default: -Context: server, location, ifredirect;#临时重定向,重写完成后以临时重定向⽅式直接返回重写后⽣成的新URL给客⼾端,由客⼾端重新发起请求;使⽤相对路径,或者http://或https://开头,状态码:302permanent;#重写完成后以永久重定向⽅式直接返回重写后⽣成的新URL给客⼾端,由客⼾端重新发起请求,状态码:301last;#重写完成后停⽌对当前URI在当前location中后续的其它重写操作,⽽后对新的URL启动新⼀轮重写检查,不建议在location中使⽤break;#重写完成后停⽌对当前URL在当前location中后续的其它重写操作,⽽后直接将匹配结果返还给客⼾端即结束循环并返回数据给客⼾端,建议在location中使⽤
2.2 rewrite之永久与临时重定向
需求:将访问源域名www.hechunping.tech的请求永久重定向到www.hechunping.com
2.2.1 永久重定向
[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location / { root html; index index.html; rewrite ^(.*)$ http://www.hechunping.com$1 permanent; }}[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/www.hechunping.com.conf server { listen 80; server_name www.hechunping.com; location / { root html/hechunping; index index.html; }}[root@CentOS7-01 ~]#cat /apps/nginx/html/hechunping/index.html hechunping web[root@CentOS7-01 ~]#systemctl reload nginx# 访问测试
2.2.2 临时重定向
将www.hechunping.tech域名配置文件rewrite指令后面的permanent去掉,或者指定为redirect即可# 访问测试
2.2.3 两者区别
永久重定向:返回的状态码是301,告诉浏览器域名是固定重定向到当前⽬标域名,后期不会更改了。拿上面的例子来说就是将www.hechunping.tech永久重定向到www.hechunping.com。临时重定向:返回的状态码是302,告诉浏览器域名不是固定重定向到当前⽬标域名,后期可能随时会更改,因此浏览器不会缓存当前域名的解析记录,⽽浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最⼤的本质区别。
2.3 rewrite之break与last
需求:访问break的请求被转发⾄test1,⽽访问test1传递请求再次被转发⾄test2,以此测试last和break分别有什么区别:
2.3.1 break
[root@CentOS7-01 ~]#mkdir /apps/nginx/html/{break,test{1,2}}[root@CentOS7-01 ~]#echo "break" > /apps/nginx/html/break/index.html[root@CentOS7-01 ~]#echo "test1" > /apps/nginx/html/test1/index.html[root@CentOS7-01 ~]#echo "test2" > /apps/nginx/html/test2/index.html[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.confserver { listen 80; server_name www.hechunping.tech; location /break { root html; index index.html; rewrite ^/break/(.*)$ /test1/$1 break; rewrite ^/test1/(.*)$ /test2/$1 break; }}[root@CentOS7-01 ~]#systemctl reload nginx[root@CentOS7-01 ~]#curl http://www.hechunping.tech/break/index.htmltest1
2.3.2 last
[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location /break { root html; index index.html; rewrite ^/break/(.*)$ /test1/$1 last; } location /test1 { root html; index index.html; rewrite ^/test1/(.*)$ /test2/$1 break; }}[root@CentOS7-01 ~]#systemctl reload nginx[root@CentOS7-01 ~]#curl http://www.hechunping.tech/break/index.htmltest2
2.3.3 两者区别
break:匹配成功后不再向下匹配,也不会跳转到其他的location,即直接结束匹配并给客⼾端返回结果数据。break适⽤于不改变客⼾端访问⽅式,但是要将访问的⽬的URL做单次重写的场景,⽐如有V1/V2两个版本的⽹站前端⻚⾯并存,旧版本的⽹站数据已经保存到了static不能丢失,但是要将访问新版本的资源重写到新的静态资源路径到新的⽬录newstatic:location /static {root /data/nginx;index index.html;rewrite ^/static/(.*) /newstatic/$1 break;}last:对某个location的URL匹配成功后会停⽌当前location的后续rewrite规则,并结束当前location,然后将匹配⽣成的新URL跳转⾄其他location继续匹配,直到没有location可匹配后将最后⼀次location的数据返回给客⼾端。last适⽤于要不改变客⼾端访问⽅式但是需做多次⽬的URL重写的场景,场景不是很多。
2.4 rewrite之⾃动跳转https
[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; if ($scheme = http ){ rewrite ^(.*)$ https://$server_name$request_uri permanent; }}server { listen 443 ssl; server_name www.hechunping.tech; ssl_certificate /apps/nginx/certs/www.hechunping.tech.crt; ssl_certificate_key /apps/nginx/certs/www.hechunping.tech.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; location / { root /apps/nginx/html/pc; index index.html; }}[root@CentOS7-01 ~]#systemctl reload nginx访问测试
2.5 rewrite之判断⽂件是否存在
[root@CentOS7-01 ~]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location / { root /apps/nginx/html/pc; index index.html; if ( !-f $request_filename ) { rewrite ^(.*)$ http://www.hechunping.tech/index.html; } }}[root@CentOS7-01 ~]#systemctl reload nginx[root@CentOS7-01 ~]#ls /apps/nginx/html/pc/index.html[root@CentOS7-01 ~]#cat /apps/nginx/html/pc/index.html pc web访问测试
从上图结果中可以发现,请求的uri sdafda不存在,而后做了302临时重定向到http://www.hechunping.tech/index.html
3 Nginx防盗链
防盗链基于客⼾端携带的referer实现,referer是记录打开⼀个⻚⾯之前记录是从哪个⻚⾯跳转过来的标记信息,如果别⼈只链接了⾃⼰⽹站图⽚或某个单独的资源,⽽不是打开了⽹站的整个⻚⾯,这就是盗链,referer就是之前的那个⽹站域名,正常的referer信息有以下⼏种:none:请求报⽂没有referer⾸部,⽐如⽤⼾直接在浏览器输⼊域名访问web⽹站,就没有referer信息。blocked:请求报文有referer⾸部,但⽆有效值,⽐如为空。server_names:referer⾸部中包含本主机名及即nginx 监听的server_name。arbitrary_string:⾃定义指定字符串,但可使⽤*作通配符。regular expression:被指定的正则表达式模式匹配到的字符串,要使⽤~开头,例如: ~.*\.hechunping\.com。正常通过搜索引擎搜索web网站并访问该网站的referer信息如下:[root@CentOS7-01 ~]#tail -f /data/nginx/logs/www.hechunping.tech/access.log {"@timestamp":"2020-01-07T15:20:43+08:00","host":"192.168.7.71","clientip":"192.168.7.1","size":138,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.hechunping.tech","uri":"/","domain":"www.hechunping.tech","xff":"-","referer":"https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=www.hechunping.tech&rsv_pq=e28a73dc000305f6&rsv_t=56aau6YPtkwVFUsn6WxxW25Eujtv3MwkIOSZI1txkxGY5RgRI3GdmfDHzEM&rqlang=cn&rsv_enter=1&rsv_dl=ib&rsv_sug3=20&rsv_sug1=8&rsv_sug7=101","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0","status":"302"}
3.1 实现web盗链
在www.hechunping.tech这个网站盗链www.hechunpig.com网站的a1.jpg图片# www.hechunping.tech网站的nginx配置[root@CentOS7-01 image]#cat /apps/nginx/conf/vhosts/pc.conf server { listen 80; server_name www.hechunping.tech; location / { root /apps/nginx/html/pc; access_log /data/nginx/logs/www.hechunping.tech/access.log access_json; index index.html; }}[root@CentOS7-01 image]#cat /apps/nginx/html/pc/index.html 盗链页面 测试盗链# www.hechunping.com网站的nginx配置[root@CentOS7-01 image]#cat /apps/nginx/conf/vhosts/www.hechunping.com.conf server { listen 80; server_name www.hechunping.com; location ~* \.(png|jpg)$ { root html/image; access_log /data/nginx/logs/www.hechunping.com/access.log access_json; }}[root@CentOS7-01 image]#ls /apps/nginx/html/image/aa.jpg[root@CentOS7-01 image]#cat /apps/nginx/html/hechunping/index.html hechunping web[root@CentOS7-01 image]#systemctl reload nginx#访问测试在www.hechunping.com站点的访问日志中可以看到访问/aa.jpg是从"referer":"http://www.hechunping.tech这个地址过来的[root@CentOS7-01 image]#tail -n1 /data/nginx/logs/www.hechunping.com/access.log {"@timestamp":"2020-01-07T17:15:52+08:00","host":"192.168.7.71","clientip":"192.168.7.1","size":425253,"responsetime":0.048,"upstreamtime":"-","upstreamhost":"-","http_host":"www.hechunping.com","uri":"/aa.jpg","domain":"www.hechunping.com","xff":"-","referer":"http://www.hechunping.tech/","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36","status":"200"}
3.2 实现防盗链
基于访问安全考虑,nginx⽀持通过ngx_http_referer_module模块检查访问请求的referer信息是否有效,官方文档:https://nginx.org/en/docs/http/ngx_http_referer_module.html#valid_referers实现防盗链功能,定义⽅式如下:[root@CentOS7-01 image]#cat /apps/nginx/conf/vhosts/www.hechunping.com.conf server { listen 80; server_name www.hechunping.com; location ~* \.(png|jpg)$ { root html/image; access_log /data/nginx/logs/www.hechunping.com/access.log access_json; valid_referers none blocked server_names *.hechunping.com api.online.test/v1/hostlist ~\.google\. ~\.baidu\.; if ($invalid_referer) { return 403; } }}[root@CentOS7-01 image]#ls /apps/nginx/html/image/aa.jpg[root@CentOS7-01 image]#systemctl reload nginx# 访问测试在www.hechunping.com站点的访问日志中可以看到"referer":"http://www.hechunping.tech 状态码403[root@CentOS7-01 image]#tail -n1 /data/nginx/logs/www.hechunping.com/access.log {"@timestamp":"2020-01-07T17:49:43+08:00","host":"192.168.7.71","clientip":"192.168.7.1","size":548,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.hechunping.com","uri":"/aa.jpg","domain":"www.hechunping.com","xff":"-","referer":"http://www.hechunping.tech/","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36","status":"403"}
指令
配置
条件
变量
域名
字符
状态
资源
永久
表达式
测试
结果
字符串
正则
浏览器
网站
路径
浏览
信息
地址
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
乐至软件开发工资一般多少
网络安全师岗位说明
阿里云服务器月流量包是什么意思
数据库与缓存关系
一季度乡镇网络安全工作总结
阿里云服务器怎么申请
浙江民信网络技术有限公司
mysql数据库热备份
静海区网络技术答疑解惑
中国的网络安全情况调查
软件开发的形势分析
量子时代还有网络安全吗
普陀区大型网络技术采购信息
淄博创盈软件开发有限公司招聘
gta线上模式怎么开服务器
服务器系统共享
档案管理系统服务器存储器大小
中小学网络安全法知识答题
株洲软件开发培训哪家强
线上线下软件开发
如何来推税控服务器
服务器的安全方法
数据库事务的四个基本性质
提高电子商务网络安全的方法
mongo 数据库排序
公安谋划网络安全工作
阿鲁高服务器都转到哪里了
泰康人寿软件开发岗
web服务器端开发技术
武汉小马驹网络技术