一、什么是Rewrite
Rewrite也称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。
1. URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。比如http://www.123.com/news/index.php?id=123 使用URLRewrite 转换后可以显示为 http://www.123.com/news/123.html
2. 从安全角度上讲,如果在url中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的url地址可以给我们带来更高的安全性。
3. 实现网站地址跳转、盗链。
二、Rewrite相关指令
Nginx Rewrite相关指令有if、rewrite、set、return等。
1、if指令
if 的语法 if (condition) { … }
应用于server和location环境内(if 与条件之间必须有空格)
if 可以支持如下条件判断匹配符号
~ 为区分大小写匹配
~* 为不区分大小写匹配
!~和!~* 分别为区分大小写不匹配及不区分大小写不匹配
-f 和!-f 用来判断是否存在文件
-d 和!-d 用来判断是否存在目录
-e 和!-e 用来判断是否存在文件或目录
-x 和!-x 用来判断文件是否可执行
在匹配过程中可以引用一些Nginx的全局变量,更多的变量请参考 http://wiki.nginx.org/NginxHttpCoreModule 的 Variables 部分
$args 请求中的参数;
$document_root 针对当前请求的根路径设置值;
$host 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate 对连接速率的限制;
$request_method 请求的方法,比如"GET"、"POST"等;
$remote_addr 客户端地址;
$remote_port 客户端端口号;
$remote_user 客户端用户名,认证用;
$request_filename 当前请求的文件路径名(带root指定的路径,即网站的主目录)
$request_uri 当前请求的文件路径名(不带root指定的路径)
$query_string 与$args相同;
$scheme 所用的协议,比如http或者是https
$server_protocol 请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name 请求到达的服务器名;
$document_uri 与$uri一样,URI地址;
$server_port 请求到达的服务器端口号;
last stops processing the current set of ngx_http_rewrite_module directives and starts a search for a new location matching the changed URI; 相当于Apache里的[L]标记,表示完成rewrite
break stops processing the current set of ngx_http_rewrite_module directives as with the break directive; 本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect returns a temporary redirect with the 302 code; used if a replacement string does not start with “http://” or “https://”; 返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent returns a permanent redirect with the 301 code.返回301永久重定向,浏览器地址会显示跳转后URL地址
rewrite /(.*)\.php$ /$1.html break;
(.*)任意字符长度
.php$ 以php结尾
$1引用前边的(.*)
任意请求php结尾的网页转到html网页 然后跳出
if ( !-f $request_filename) { 如果请求的文件不存在则执行以下操作
rewrite ^/(.*)$ /test.html last; 任意不存在的网页请求装给test.html网页 last 继续替换
}
2、使用rewrite命令实现防盗链
1.盗链(html)
[root@server3 ~]# vim /var/www/html/index.html
<a href="http://192.168.50.103/aa.txt">nginx</a>
2.防盗链nginx
[root@server3 ~]# vim /usr/local/nginx/conf/nginx.conf
#添加如下此 Nginx 配置片段用于防止未经授权的站点直接链接到 .txt 文件。只有当请求的 referer 来自 www.robin.com、没有 referer 头、或 referer 头被阻塞时,请求才会被认为是有效的。否则,请求将被重定向到一个指定的错误页面(http://192.168.10.100/gun.html),或者如果取消注释 return 404; 行,则返回 404 错误
location ~* \.(txt)$ { #使用正则表达式匹配所有以 .txt 结尾的请求。~* 表示不区分大小写的匹配valid_referers none blocked www.robin.com; #定义哪些 referer 是有效的,没有referer valid_referer=1if ($invalid_referer) {rewrite ^/ http://192.168.50.103/gun.html;#return 404;}}
none 代表没有referer
blocked 代表有referer但是被防火墙或者是代理给去除了
none the“Referer” field is missing in the request header; (即直接在客户端浏览器地址栏中输入的)
blocked the“Referer” field is present in the request header, but its value has been deleted by a firewall or proxy server; such values are strings that do not start with “http://” or “https://”;
server_names the “Referer” request header field contains one of the server names;
arbitrary string defines a server name and an optional URI prefix. A server name can have an “*” at the beginning or end. During the checking, the server’s port in the “Referer” field is ignored;
regular expression the first symbol should be a “~”. It should be noted that an expression will be matched against the text starting after the “http://” or “https://”
rewrite 指令根据表达式来重定向URI,或者修改字符串。可以应用于server,location, if环境下
每行rewrite指令最后跟一个flag标记,支持的flag标记有:
last 相当于Apache里的[L]标记,表示完成rewrite,然后继续匹配后续规则
break 本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent 返回301永久重定向,浏览器地址会显示跳转后URL地址
redirect 和 permanent区别则是返回的不同方式的重定向,对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,
如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改,那么很有可能出现URL劫持的现像。
参考示例:
例1:
http://www.test.com/test/abc/1.html ⇒ http://www.test.com/ccc/bbb/2.html
location /test{rewrite .* /ccc/bbb/2.html permanent;
}
例2:
http://www.test.com/2015/12/10/2.html ==> http://www.test.com/2014/12/10/2.html
location /2015 {rewrite ^/2015/(.*)$ /2014/$1 permanent; #引用
}
例3:
http://www.test.com/2015/ccc/bbb/2.html ==> http://jd.com/index.php
location /2015{if ($host ~* www.test.com) {rewrite .* http://www.jd.com/index.php permanent;}
}
例4:
#http://www.test.com/kkk/1.html ==> http://jd.com/kkk/1.html
location / {
root html;
index index.html index.htm;
if ($host ~* www.test.com) {rewrite .* http://www.jd.com/$request_uri permanent;}
}
例5:
有时候在访问一个二级子目录时会出现目录后的/无法补齐,如:
[root@localhost html]# elinks --dump www.test.com/www/xxx 无法访问
[root@localhost html]# elinks --dump www.test.com/www/可以访问
if ( -d $request_filename) {rewrite ^(.*)([^/])$ http://$host$1$2/ permanent;
}
^/(.*)([^/])$表示以/符号开始并紧跟着任何字符,同时不是以/为结束的字符串,在我的url中,(.*)表示的www,([^/])表示的不是以/结束的字符串
例6:
#http://www.test.com/login/robin.html ==> http://www.test.com/reg/login.php?user=robin
location /login {rewrite ^/login/(.*)\.html$ /reg/login.php?user=$1 permanent;
}
例7:
http://www.test.com/uplook/2000-12-20.html ==> http://www.test.com/uplook/2000/11/20.html
location /uplook {rewrite ^/uplook/([0-9]+)-([0-9]+)-([0-9]+)\.html$ /uplook/$1/$2/$3.html permanent
}
set 指令是用于定义一个变量,并且赋值。应用于server,location,if环境。
例8:
#http://robin.test.com ==> http://www.test.com/robin
#http://zorro.test.com ==> http://www.test.com/zorro
[root@root html]# mkdir robin zorro
[root@root html]# echo robin.... > robin/index.html
[root@root html]# echo zorro... > zorro/index.html
a. DNS实现泛解析
*.test.com IN A 网站IP
b. nginx Rewrite
if ($host ~* "^www.test.com$" ) {break;
}
if ($host ~* "^(.*)\.test\.com$" ) {set $user $1;rewrite .* http://www.test.com/$user permanent;
}
return 指令用于返回状态码给客户端,应用于server,location,if环境。
例9:如果访问的.sh结尾的文件则返回403操作拒绝错误
location ~* \.sh$ {return 403;
}