一、什么是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;
}