一、Rewrite基本介绍

1.1 什么是Rewrite

Rewrite主要实现url地址重写, 以及url地址跳转。就是将用户请求web服务器的URL地址重新修改为其他URL地址的过程。
比如说京东,google、亚马逊都在使用

域名重写后域名
www.z.cnwww.amazon.cn
www.g.cnwww.google.cn
www.360buy.comwww.jd.com
58.combj.58.com

1.2 Rewrite应用场景

  1. 地址跳转,用户访问www.jd.com这个URL时,将其定向至一个新的域名m.jd.com
  2. 协议跳转,将用户通过http的请求协议重新跳转至https协议(实现https主要手段)。
  3. URL静态化,将动态URL地址显示为静态URL的一种技术,能提高搜索引擎抓取,并且能减少动态URL对外暴露过多的参数。

1.3 Rewrite重写原理

在这里插入图片描述

1.4 Rewrite重写模块

  • set 设置变量
  • if 语句判断
  • return 返回返回值或URL
  • rewrite 重定向URL

二、Rewrite重写模块

2.1 if条件判断指令

语法:

Syntax: if (condition) { ... }
Default: —
Context: server, location
# ~ 模糊匹配 
# ~* 不区分大小写的匹配
# !~ 不匹配 
# = 精确匹配

示例:
需求:匹配Nginx请求中包含id=1234的,然后代理到 10.16.3.5 的8080端口

[root@web01 conf.d]# cat url1.conf 
server {
	listen 80;
	server_name url1.bertwu.net;
	root /code;
	location / {
		index index.html;
		if ( $request_uri ~* 'id=\d{4}' ) {
			proxy_pass http://10.16.3.5:8080;
			
		}
	}
}

2.2 set设定变量指令

语法:

Syntax: set $variable value;
Default: —
Context: server, location, if

示例:

# 需求:通过user_agent(Header)拦截压测测试工具、程序爬虫等
# user_agent:
# chrome ,firefox, curl/7.29.0
# 1.确认来请求的用户是使用的curl命令,如果是则做一个标记,设置为1;
# 2.判断标记,如果标记的值假设为1,我们就拒绝,如果不为1则不处理;
[root@web01 conf.d]# cat set.conf 
server {
	listen 80;
	server_name set.bertwu.net;
	root /code;
	location / {
		index index.html;
		if ( $http_user_agent ~* 'curl|python|wget|apachbench' ) {
			set $flag 1;
		}
		if ( $flag = 1 ) {
			return 403;
		}	
	}
}

访问,被禁止
root@web02 ~]# curl -H Host:set.bertwu.net http://10.0.0.7:80
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.20.1</center>
</body>
</html>

2.3 return返回数据指令

语法:

Syntax: 
return code;
return code [text];
return URL;
Default: —
Context: server, location, if

示例
需求:客户端使用IE或火狐浏览器访问站点,则返回段字符串或返回错误或重定向

server {
	listen 80;
	server_name ret.bertwu.net;
	root /code;
	charset utf-8;
	location / {
		index index.html;
		default_type text/html;
		if ( $http_user_agent ~* "MSIE|firefox|trident" ) {
			#return 500;	# 返回状态码
			return 200 "Change Brower..."; # 返回状态码+text
			#return 302 https://www.baidu.com;	# 返回 code + url
		}

	}
}

三、Rewrite重写Flag

rewrite主要是用来重写URL或者跳转URL的指令。

#rewrite表达式可以应用在server,location, if标签下

#       关键字   正则   替代内容     flag标记
 Syntax: rewrite regex replacement [flag];
 Default: --
 Context: server, location, if

 #flag
 last        #本条规则匹配完成后,继续向下匹配新的location URI规则
 break       #本条规则匹配完成即终止,不再匹配后面的任何规则

 redirect    #返回302临时重定向, 地址栏会显示跳转后的地址
 permanent   #返回301永久重定向, 地址栏会显示跳转后的地址

3.1 测试准备

[root@web01 conf.d]# cat rewrite.conf 
server {
	listen 80;
	server_name rew.bertwu.net;
	root /code/code1;
	location / {
		rewrite /1.html /2.html;
		rewrite /2.html /3.html;
	}
	location /2.html {
		rewrite /2.html /a.html;
	}
	location /3.html {
		rewrite /3.html /b.html; 
	}
}

[root@web01 conf.d]# echo "1.html" >/code/code1/1.html
[root@web01 conf.d]# echo "2.html" >/code/code1/2.html
[root@web01 conf.d]# echo "3.html" >/code/code1/3.html
[root@web01 conf.d]# echo "a.html" >/code/code1/a.html
[root@web01 conf.d]# echo "b.html" >/code/code1/b.html

#结果:当请求/1.html,最终将会访问/b.html

3.2 Break与last

3.2.1 Break

在location{}内部,遇到break,本location{}内以及后面的所有location{}内的所有指令都不再执行

[root@web01 conf.d]# cat rewrite.conf 
server {
	listen 80;
	server_name rew.bertwu.net;
	root /code/code1;
	location / {
		rewrite /1.html /2.html break;
		rewrite /2.html /3.html;
	}
	location /2.html {
		rewrite /2.html /a.html;
	}
	location /3.html {
		rewrite /3.html /b.html; 
	}
}

测试结果: 当请求/1.html,最终会访问/2.html
在这里插入图片描述

3.2.2 last

在location{}内部,遇到last,本location{}内后续指令不再执行,而重写后的url会对所在的server{…}标签重新发起请求,从头到尾匹配一遍规则,哪个匹配则执行哪个。

[root@web01 conf.d]# cat rewrite.conf 
server {
	listen 80;
	server_name rew.bertwu.net;
	root /code/code1;
	location / {
		rewrite /1.html /2.html last;
		rewrite /2.html /3.html;
	}
	location /2.html {
		rewrite /2.html /a.html;
	}
	location /3.html {
		rewrite /3.html /b.html; 
	}
}

测试结果:当请求/1.html,最终会访问/a.html
在这里插入图片描述

3.2.3 break与last区别

  • 当rewrite规则遇到break后,本location{}与其他location{}的所有规则都不执行。
  • 当rewrite规则遇到last后,本location{}里后续规则不执行,但重写后的url会再次从头开始匹配所有Location,哪个匹配执行哪个。

3.3 redirect与permanent

3.3.1 为代码添加redirect

[root@web01 conf.d]# cat rewrite.conf 
server {
	listen 80;
	server_name rew.bertwu.net;
	root /code/code1;
	location / {
		rewrite /1.html /2.html last;
		rewrite /2.html /3.html;
	}
	location /2.html {
		rewrite /2.html /a.html;
	}
	location /3.html {
		rewrite /3.html /b.html; 
	}
}

在这里插入图片描述

3.3.2 为代码添加permanent

[root@web01 conf.d]# cat rewrite.conf 
server {
	listen 80;
	server_name rew.bertwu.net;
	root /code/code1;
	location / {
		rewrite /1.html /2.html last;
		rewrite /2.html /3.html;
	}
	location /2.html {
		rewrite /2.html /a.html;
	}
	location /3.html {
		rewrite /3.html /b.html; 
	}
}

在这里插入图片描述

3.3.3 redirect与permanent区别

  • redirect临时跳转302,对旧网站无影响,新网站会有排名(不会缓存)
  • permanent永久跳转301,对新跳转网站有排名,旧网站排名会被清空(缓存下来)

四、Rewrite 生产案例实践

  1. 需求:根据用户浏览器请求头中携带的语言调度到不同的页面
[root@web01 conf.d]# cat language.conf 
server {
	listen 80;
	server_name lan.bertwu.net;
	root /code/code1;
	if ( $http_accept_language ~* 'zh-CN|zh' ) {
		set $language zh;
	}
	if ( $http_accept_language ~* 'en' ) {
		set $language en;
	}
	rewrite ^/$ /$language;
	location / {
		index index.html;
	}
}
  1. 需求:用户通过手机设备访问 agent.bertwu.net,跳转至agent.bertwu.net/m
[root@web01 conf.d]# cat agent.conf 
server {
	listen 80;
	server_name agent.bertwu.net;
	root /code;
	if ($http_user_agent ~* 'iphon|android|ipad') {
		rewrite ^/$ /m;

	}
	location / {
		index index.html;
	}
}

[root@web01 conf.d]# echo 'chrom---' > /code/index.html
[root@web01 conf.d]# mkdir /code/m;
[root@web01 conf.d]# echo 'android---' > /code/m/index.html

在这里插入图片描述
3. 用户通过手机设备访问 url.bertwu.net跳转至 m.bertwu.net

[root@web01 conf.d]# cat m.bertwu.conf 
server {
	listen 80;
	server_name url.bertwu.net;
	root /code;
	if ( $http_user_agent ~* 'android|iphone|ipad' ) {
		rewrite ^/$ http://m.url.bertwu.net redirect;
	}
	location / {
		index index.html;
	}
}

server {
	listen 80;
	server_name m.url.bertwu.net;
	root /code/m;
	location / {
		index index.html;
	}
}

  1. 需求:用户通过http协议请求,能自动跳转至https协议。
server {
    listen 80;
    server_name url.bertwu.net;
    root /code1;


	# $http_host 
	# $server_name
	# $host 这三种方式一样
	
	return 302 https://$http_host$request_uri;
	#rewrite ^(.*)$ https://$http_host$1 redirect;
}


server {
	listen 443;
	server_name url.bertwu.net;

	location / {
	}
}

5.网站维护过程中,希望所有用户请求重新跳转到一个页面

server {
    listen 80;
    server_name url.bertwu.net;
    root /code;

	# 直接写在server层,防止过多的location重复写,维护页面的开关
	#  rewrite ^(.*)$ /wh.html break;

	location / {
		index index.html;
	}

6.需求:当服务器遇到403404 502等错误时,自动转到临时维护的静态页。

server {
    listen 80;
    server_name url.bertwu.net;
    root /code;


	location / {
		index index.html;
	}
	
	error_page 404 403 502 @errorpage
	
	location @errorpage {
		rewrite ^(.*)& /wh.html break
	}

7.对部分ip放行,对其他ip进入停机维护

server {
    listen 80;
    server_name url.bertwu.net;
    root /code1;

  # 设定ip变量为0
	set $ip 0;
	# 判断,如果来源的IP为节点的IP则设定ip变量为1,如果前面有七层负载均衡,建议使用 $http_x_forwarded_for
	if ($remote_addr ~ "10.0.0.1|10.0.0.2") {
		set $ip 1;
	}

	# 判断 如果ip变量为0 ,则进入维护页面;
	if ($ip = 0) {
		rewrite ^(.*)$ /wh.html break;
	}	

	location / {
		index index.html;	
	}
}

# 如果只需要对特定的location做限制,把上面写在特定location中即可

8.公司后台/admin 只允许公司出口IP可以访问,其他全部返回500或跳转首页

location /admin {
		limit_rate 100k;

		set $ip 0;
		if ($remote_addr ~ "10.0.0.51") {
			set $ip 1;
		}
		if ($ip = 0) {
			#return 404;		
			#return 302 http://$http_host;
		}
	}

在这里插入图片描述

server {
    listen 80;
    server_name url.bertwu.net;
    root /code1;

	location / {
		index index.html;

		if ($http_host ~* (.*)\.(.*)\.(.*) ) {
			set  $domain $1;
		}
		
		rewrite ^(.*)$ http://demo:27610/$domain$request_uri redirect;
	}
}

五、防盗链配置

防盗链,指的是防止资源被其他网站恶意盗用。如何避免网站资源被盗用:可以根据客户端请求所携带的Referer信息来验证请求的合法性,因为Referer会告诉服务器它是从哪一个域名点击过来的。
基于Referer限制盗链:
优点:规则简单、配置和使用都很方便,
缺点:防盗链所依赖的Referer验证信息是可以伪造的,并非100%可靠;但基于Referer限制盗链的方式,可以限制绝大多数盗链情况。
环境:

角色IP域名
盗链节点(偷取资源)10.0.0.7sb.laowang.net
被盗链节点(提供资源)10.0.0.8img.bertwu.net

1.配置被盗链节点

[root@web02 conf.d]# cat img.bertu.conf 
server {
	listen 80;
	server_name img.bertwu.net;
	root /code;
	location / {
		index index.html;
	}
}

然后往根目录下放置一张照片

2.配置盗链节点

[root@web01 conf.d]# cat www.bertwu.conf 
server {
	listen 80;
	server_name sb.laowang.net;
	root /code;
	location / {
		index index.html;
	}
}

# index.html内容
[root@web01 conf.d]# cat /code/index.html 
<html>
<head>
	<meta charset="utf-8">
	<title>bertwu.net</title>
</head>
<img src="http://img.bertwu.net/xld.jpg"/>
</html>

3.访问sb.laowang.ne,可以直接盗取图片
在这里插入图片描述

防盗语法:

# 基于http_referer防止资源被盗用
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location
#none: Referer来源头部为空的情况(通常是浏览器直接访问)
#blocked: Referer来源头部不为空,直接填写允许的域名即可
#server_names: 来源头部包含当前的域名,可以正则匹配

4.防盗配置:
配置所有来自*.bertwu.com都可以访问到img.bertwu.net站点的图片。如果来源域名不在这个列表中,那么$invalid_referer变量值为1,后续通过if判断,进行错误返回;

[root@web02 conf.d]# cat img.bertu.conf 
server {
	listen 80;
	server_name img.bertwu.net;
	root /code;
	
	location / {
		index index.html;
	}
	
	location ~ .*\.(jpg|jpeg|gif|png)$ {
		valid_referers none blocked *.bertwu.net; # 如果走我这里 invalid_referer为0 否则非零
		if ($invalid_referer) {
			return 403; 
		}
	}
}

再次访问,发现已经失败。

在这里插入图片描述

# 允许 google、baidu、等站点能够(盗链)资源,那么则可以通过server_names开放   
 # location ~* \.(gif|jpg|png|bmp)$ {         
 		valid_referers none blocked *.bertwu.net server_names ~\.google\. ~\.baidu\.;

如果检测到被盗,也可以返回一张恶搞图片

[root@web02 conf.d]# cat img.bertu.conf 
server {
	listen 80;
	server_name img.bertwu.net;
	root /code;
	
	location / {
		index index.html;
	}
	
	location ~ .*\.(jpg|jpeg|gif|png)$ {
		valid_referers none blocked *.bertwu.net;
		if ($invalid_referer) {
			rewrite ^(.*)$ /error.jpg break; 
		}
	}
}

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐