Nginx服務器利用ngx_http_rewrite_module模塊解析和處理rewrite請求。rewrite用於實現URL的重寫,相似於重定向功能,能夠將用戶的請求重寫至別的目錄,另外還能夠在必定程度上提升網站的安全性。html
https://nginx.org/en/docs/http/ngx_http_rewrite_module.htmllinux
用於條件匹配判斷,根據條件判斷結果選擇不一樣的nginx配置,在server或location中配置。nginx的if語法只能支持單次判斷,不支持多重判斷,用法以下nginx
if (條件匹配) { action } #示例1 location /main { index index.html; default_type text/html; if ( $scheme = http ){ echo "if ---> $scheme"; } if ($scheme = https ){ echo "if ---> $scheme"; } }
使用正則表達式對變量進行匹配,成功爲true,不然false,變量與表達式之間能夠用符號連接:web
= #比較變量與字符串是否相等 ~ #表示在匹配過程當中區分大小寫字符 ~* #表示在匹配過程當中不區分大小寫 -f 和 !-f #判斷請求的文件存在與不存在 -d 和 !-d #判斷請求的目錄存在與不存在 -x 和 !-x #判斷文件是否可執行 -e 和 !-e #判斷請求的文件或目錄是否存在(包括文件,目錄,軟連接)
注:若$變量的值爲空或以0開頭,則if指令認爲此條件爲false,其它條件爲true正則表達式
指定key並給其定義一個變量,定義格式爲set $key value,只有將內置變量賦值給自定義變量時不管是key仍是value都要加$符號express
location /main { root /data/html; index index.html; default_type text/html; set $name javis; echo $name; set $my_port &server_port; echo $my_port; }
用於中斷當前相同做用域(location)中的其餘配置,中止向下尋找,回到上一層做用域繼續向下讀取配置,該指令可在server塊和location塊以及ig塊中使用,語法以下:vim
location /main { root /data/html; index index.html; default_type text/html; set $name javis; echo $name; break; set $my_port &server_port; echo $my_port; } #只輸出$name的值javis,再也不向下執行
return用於完成隊請求的處理,並直接向客戶端返回響應狀態碼處於此指令後的全部配置都將不被執行,return能夠在server、if和location塊進行配置,語法以下centos
return code #返回給客戶端指定的http狀態碼 return code (text) #返回給客戶端指定的狀態碼及響應內容,能夠調用變量 return code URL #返回給客戶端的URL地址 示例1 location /main { root /data/html; index index.html; default_type text/html; if ( $scheme = http ){ return 500 "server error"; echo "if --->" $scheme; #只輸出server error,後面的將不執行 } if ( $scheme = https){ echo "if --->" $scheme; } }
設置是否開啓記錄ngx_http_rewrite_module模塊日誌記錄到error_log日誌文件中,能夠配置在http、server、location或if當中,須要日誌級別爲noticeapi
location /main { root /data/html; index index.html; default_type text/html; set $name javis; echo $name; rewrite_log on; break; set $my_port &server_port; echo $my_port; } #重啓nginx,訪問error_log
經過正則表達式的匹配倆改變URI,能夠同時存在一個或多個指令,按照次序對URI進行匹配,rewrite主要是針對用戶請求的URL或URI做具體處理瀏覽器
URI:通用資源標識符,標識一個資源的路徑,能夠不帶協議 URL:統一資源定位符,用於在internet中描述資源的字符串,時URI的子集,主要包括傳輸協議(scheme)、主機(IP、端口號或者域名)和資源具體地址(目錄和文件名)等三部分,通常格式爲 scheme://主機名[:端口號][/資源路徑],如:http://www.a.com:8080/path/file/index.html就是一個URL路徑,URL必須帶訪問協議。 區別:每個URL都是URI,但URI不都是URL 示例: http://example.org/path/to/resource.txt #URI/URL ftp://example.org/resource.txt #URI/URL /absolute/path/to/resource.txt #URI
rewrite官方介紹:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite,能夠配置在server、location、if中,語法以下:
rewrite regex replacement [flag];
rewrite將用戶請求的URI基於regex所描述的模式進行檢查,匹配到時將其替換爲表達式指定的新的URI。若在同一級配置模塊中存在多個rewrite規則,就會自上而下逐個檢查;被某規格替換後,會從新一輪新的替換檢查,隱含有循環機制,但不超過10次;若超過則提示500響應嗎,[flag]所標識的標誌位用於控制此循環機制,,若是替換後的URL是以http://或https://開頭,則替換結果會以重定向返回客戶端,即永久重定向301
利用nginx的rewrite的指令,能夠實現url的從新跳轉,rewrtie有四種不一樣的flag,分別是redirect(臨時重定向)、permanent(永久重定向)、break和last。其中前兩種是跳轉型的flag,後兩種是代理型,跳轉型是指有客戶端瀏覽器從新對新地址進行請求,代理型是在WEB服務器內部實現跳轉的。
redirect #臨時重定向,重寫完成後以臨時重定向方式直接返回重寫後生成的新URL給客戶端,有客戶端從新發起請求,使用相對路徑,http://或https://開頭,狀態碼:302 permanent #永久重定向,以永久重定向的方式直接返回重寫後生成的新URL給客戶端,由客戶端從新發起新的請求,狀態碼:301 last #重寫完成後中止對當前location中後續的其餘重寫操做,然後對新的URL啓動新一輪重寫檢查,不建議在location中使用 break #重寫完成後中止對當前URL在當前location中後續的其餘重寫操做,然後直接跳轉至重寫規則匹配塊以後的其餘配置;結束循環,建議在location中使用
這裏應該瞭解nginx處理的十一個階段
NGX_HTTP_POST_READ_PHASE = 0, #讀取請求頭 NGX_HTTP_SERVER_REWRITE_PHASE, #執行rewrite NGX_HTTP_FIND_CONFIG_PHASE, #根據uri替換location NGX_HTTP_REWRITE_PHASE, #根據替換結果繼續執行rewrite NGX_HTTP_POST_REWRITE_PHASE, #執行rewrite後處理 NGX_HTTP_PREACCESS_PHASE, #認證預處理 請求限制,鏈接限制 NGX_HTTP_ACCESS_PHASE, #認證處理 NGX_HTTP_POST_ACCESS_PHASE, #認證後處理, 認證不經過, 丟包 NGX_HTTP_TRY_FILES_PHASE, #嘗試try標籤 NGX_HTTP_CONTENT_PHASE, #內容處理 NGX_HTTP_LOG_PHASE #日誌處理
要求:因業務須要,將訪問原域名www.linux.net的請求永久重定向到www.linux.com
臨時重定向不會緩存域名解析記錄(A記錄),可是永久重定向會緩存
location / { root /data/html; index index.html; rewrite / http://www.linux.com permanent; #rewrite / http://www.linux.com redirect; }
(1)臨時重定向:告訴瀏覽器域名不是固定重定向到當前目標域名,後期可能隨時會更改,所以瀏覽器不會緩存當前域名的解析記錄
(2)永久重定向:永久重定向會緩存DNS解析記錄
要求:訪問break的請求被轉發至image,而訪問last傳遞請求也被轉發至image,以此測試last和break的區別
location /break { # root /data/html; rewrite ^/break/(.*) /test/$1 break;#重寫後直接直接找test目錄,若沒有爲此處的test指定根目錄,則訪問不到,換言之,若要成功跳轉,test須要完整路徑 return 666 "break"; } location /last { rewrite ^/last/(.*) /test/$1 last;#完成重寫後,在全部location裏面從新開始一輪遍歷,進到test,訪問成功 return 888 "last"; } location /test { return 999 "test"; }
重啓nginx的訪問測試
[root@centos ~]$curl -L -i www.alijiujiu.com/break/ #break不會跳轉至location /test中 HTTP/1.1 404 Not Found Server: nginx/1.14.2 Date: Sat, 01 Jun 2019 06:14:27 GMT Content-Type: text/html Content-Length: 19 Connection: keep-alive Keep-Alive: timeout=10 ETag: "5cee850d-13" this is error page [root@centos ~]$curl -L -i www.alijiujiu.com/last/ #last會跳轉至location /test中繼續執行匹配操做 HTTP/1.1 999 Server: nginx/1.14.2 Date: Sat, 01 Jun 2019 06:14:46 GMT Content-Type: application/octet-stream Content-Length: 4 Connection: keep-alive Keep-Alive: timeout=10 test
要求:基於通訊安全考慮公司網站要求全站https,因此要求將在不影響用戶請求的狀況下將http請求所有自動跳轉至https,另外也能夠實現部分location跳轉
location / { root /data/html; index index.html; if ( $scheme = http ){ #未加條件判斷,會陷入死循環 rewrite / https://www.alijiujiu.com permanent; } }
要求:當用戶訪問公司輸入錯誤的URL,能夠將用戶重定向到公司首頁
location / { root /data/html; index index.html; if ( !-f $request_filename ){ #return 404 "input error"; rewrite (.*) http://www.alijiujiu.com/index.html; } }
防盜鏈基於客戶端攜帶的referer實現,referer是記錄打開一個頁面以前記錄是從哪一個頁面跳轉過來的標記信息,若是別人只連接了本身網站圖片或某個單獨的資源,而不是打開了網站的整個頁面,這就是盜鏈,referer就是以前的那個網站域名,正常的referer信息有如下幾種
none:請求報文首部沒有referer首部,好比用戶直接在瀏覽器輸入域名訪問web網站,就沒有referer信息。 blocked:請求報文有referer首部,但無有效值,好比爲空。 server_names:referer首部中包含本主機名及即nginx 監聽的server_name。 arbitrary_string:自定義指定字符串,但可以使用*做通配符。 regular expression:被指定的正則表達式模式匹配到的字符串,要使用~開頭,例如:~.*\.magedu\.com。
5.3.1:實現防盜鏈
基於訪問安全考慮,nginx支持經過ungx_http_referer_module模塊 https://nginx.org/en/docs/http/ngx_http_referer_module.html#valid_referers 檢查訪問請求的referer信息是否有效實現防盜鏈功能,定義方式以下:
[root@centos ~]$vim /apps/nginx/conf/conf.d/pc.conf location /image { root /data/html/; index index.html; valid_referers none blocked server_names *.example.com example.* www.example.org/galleries/ ~\.google\.; if ( $invalid_referer ){ return 403; } }
實現防盜鏈:
location ^~ /images { root /data/nginx; index index.html; valid_referers none blocked server_names *.alijiujiu.com www.alijiujiu.* api.online.test/v1/hostlist ~\.google\. ~\.baidu\.; #定義有效的referer if ($invalid_referer) { #假如是使用其餘的無效的referer訪問: return 403; #返回狀態碼403 } } #重啓Nginx並訪問測試