.htaccess技巧: URL重寫(Rewrite)與重定向(Redirect)
目錄
- 一、準備開始:mod_rewrite
- 二、利用.htaccess實現URL重寫(rewrite)與URL重定向(redirect)
- 將.htm頁面對映到.php
- 臨時重定向(R=302)與永久重定向(R=301)
- 為什麼要用重定向?——重定向和URL重寫的區別
- 長短地址轉換
- 去掉www
- 加上www
- 支援多域名訪問
- 三、改寫查詢字串QUERY_STRING
- 利用QSA轉換查詢字串QUERY_STRING
- 利用RewriteCond改寫查詢字串QUERY_STRING
- QSA與RewriteCond雙劍齊發
- 剝離查詢字串
- 四、利用RewriteCond和RewriteRule進行訪問控制
- 檔案訪問控制
- 用.htaccess阻止User-agent
- 用.htaccess阻止盜鏈(hot-linking)
- References
URL重定向是.htaccess的重頭戲,它可以將長地址轉為短地址、將動態地址轉為靜態地址、重定向丟失的頁面、防止盜鏈、實現自動語言轉換等。筆者覺得難點是在正規表示式的運用和理解上。有關htaccess的正規表示式用法,請查閱本站《.htaccess正規表示式》一文。
一、準備開始:mod_rewrite
實現所有這些神奇功能的模組叫做mod_rewrite,請確保你的伺服器安裝並啟用了該模組:
sudo a2enmod rewrite
我們一般會把所有涉及URL重寫或者重定向的程式碼這樣放置:
<IfModule mod_rewrite.c>
# Turn on rewrite engine
Options +FollowSymlinks
RewriteEngine on
# More rules below
...
</IfModule>
一些我們需要注意的地方:
FollowSymlinks必須啟用,這是rewrite引擎的安全需求。
通常FollowSymlinks在Apache的主配置檔案中就已經啟用了,所以通常可以省略。
RewriteEngine命令用於啟用rewrite引擎
IfModule命令用於判斷Apache是否安裝了mod_rewrite模組,之後筆者會省略該命令,但不代表這是個好習慣。
mod_rewrite會處理所有提交給Apache的URL請求,並與之後的規則進行匹配
下面我們開始講解一些例子。
二、利用.htaccess實現URL重寫(rewrite)與URL重定向(redirect)
- 將.htm頁面對映到.php
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.htm$ $1.php [NC]
注意事項:
該RewriteRule能夠將.htm靜態頁面對映到.php動態頁面
如果通過.htm進入,瀏覽器位址列顯示的是.htm副檔名,但伺服器上實際執行的是.php
必須保證伺服器上有對應的.php,否則會404
瀏覽器和搜尋引擎可以同時通過.htm和.php訪問網頁
如果該目錄上存在.htm,將被忽略
[NC]表示“不區分大小寫”,更多類似定義請參考本站《.htaccess正規表示式》一文
- 臨時重定向(R=302)與永久重定向(R=301)
RewriteEngine on
RewriteBase /
RewriteRule ^(.*)\.htm$ $1.php [R,NC,L]
注意事項:
該RewriteRule能夠將.htm靜態頁面重定向到.php動態頁面
如果通過.htm進入,瀏覽器位址列會自動轉為.php,這也是重定向的本質
必須保證伺服器上有對應的.php,否則會404
瀏覽器和搜尋引擎可以同時通過.htm和.php訪問網頁
如果該目錄上存在.htm,將被忽略
RewriteBase定義了重寫基準目錄。
例如,如果你將虛擬站點設定在/var/www目錄下,刪除這行將會導致重定向到http://yourdomain.com/var/www/1.php。顯然這是找不到的,而且你也不會希望使用者看見你的伺服器的目錄結構。
再舉個例子,如果RewriteBase/base/,那麼將會重定向到http://yourdomain.com/base/1.php。
對於重寫基準目錄,我們還可以通過將$1.php變成/$1.php實現直接變換,這時就可以將RewriteBase省略。
字母R表示臨時重定向,相當於[R=302,NC]。關於重定向程式碼,請參考本站《HTTP協議重定向編碼》
字母L表示如果能匹配本條規則,那麼本條規則是最後一條(Last),忽略之後的規則。
在討論R=302臨時重定向後,理解R=301永久重定向也就容易多了:
RewriteEngine on
RewriteRule ^(.*)$ http://newdomain.com/$1 [R=301,NC,L]
這個規則告訴瀏覽器和搜尋引擎,網站地址發生了永久性變更,使用者的URL請求將會被髮送給新的域名(主機)處理。
由於是重定向到新的主機地址,RewriteBase也就沒有出現的必要了。
- 為什麼要用重定向?——重定向和URL重寫的區別
通過重定向,瀏覽器知道頁面位置發生變化,從而改變位址列顯示的地址
通過重定向,搜尋引擎意識到頁面被移動了,從而更新搜尋引擎索引,將原來失效的連結從搜尋結果中移除
臨時重定向(R=302)和永久重定向(R=301)都是親搜尋引擎的,是SEO的重要技術
URL重寫用於將頁面對映到本站另一頁面,若重寫到另一網路主機(域名),則按重定向處理
- 長短地址轉換
利用URL重寫,我們可以很方便地實現長短地址的轉換,但是用重定向就不合適了。
RewriteEngine On
RewriteRule ^grab /public/files/download/download.php
若訪問
http://mysite/grab?file=my.zip
則會執行該頁面:
http://mysite/public/files/download/download.php?file=my.zip
- 去掉www
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
- 加上www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(.*)$
RewriteRule (.*) http://www\.%1/$1 [R=301,L]
- 支援多域名訪問
如果你不湊巧買到了不支援多域名的主機,那麼.htaccess或許可以幫助你。現在假設你有域名domain-one.com和domain-two.com,並且在伺服器根目錄有對應資料夾one和two,那麼通過下面的改寫就能讓Apache同時接受者兩個域名的請求:
#two domains served from one root..
RewriteCond %{HTTP_HOST} domain-one.com
RewriteCond %{REQUEST_URI} !^/one
RewriteRule ^(.*)$ /one/$1 [L]
RewriteCond %{HTTP_HOST} domain-two.com
RewriteCond %{REQUEST_URI} !^/two
RewriteRule ^(.*)$ /two/$1 [L]
三、改寫查詢字串QUERY_STRING
查詢字串是指URL請求中“問號”後面的部分。比如,http://mysite/grab?foo=bar中粗體部分就是查詢字串,其中變數名是foo,值是bar。
- 利用QSA轉換查詢字串QUERY_STRING
QSA標誌( Query String Appending)用於在URI中擷取查詢字串,這個擷取操作是通過小括號正規表示式實現的:
RewriteEngine On
RewriteRule /pages/(.+) /page.php?page=$1 [QSA]
將會把請求/pages/123?one=two 對映到 /page.php?page=123&one=two
注意粗體部分幾乎是相同的,除了“問號”變成了“與”符號
如果沒有QSA標誌,那麼會對映到/page.php?page=123。
如果沒有用到小括號正規表示式,就不需要QSA,這在上節“長短地址轉換”中已經例證過了。
小括號正規表示式可以擷取查詢字串中的內容,但是如果沒有開啟QSA標誌,那麼在/page.php?page=$1中“問號”之後將會被剝離丟棄。這種特性可以用於實現“剝離查詢字串”
通過QSA,我們可以將簡單連結/simple/flat/link/ 對映成 server-side.php?first-var=flat&second-var=link
RewriteEngine On
RewriteRule ^/([^/]+)/([^/]+)/? /index.php?first-var=$1&second-var=$2 [QSA]
- 利用RewriteCond改寫查詢字串QUERY_STRING
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.*)
RewriteRule ^grab(.*) /page.php?bar=%1
該規則將訪問請求http://mysite/grab?foo=bar轉換為http://mysite/page.php?bar=bar
RewriteCond用於捕獲查詢字串(QUERY_STRING)中變數foo的值,並儲存在%1中
QUERY_STRING是Apache定義的“變數=值”向量(陣列)
- QSA與RewriteCond雙劍齊發
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.+)
RewriteRule ^grab/(.*) /%1/index.php?file=$1 [QSA]
會把/grab/foobar.zip?level=5&foo=bar 對映到 /bar/index.php?file=foobar.zip&level=5&foo=bar
轉換後根目錄是bar目錄
foobar.zip?level=5中的“問號”變成了foobar.zip&level=5中的“與”符號
- 剝離查詢字串
只需在要開始剝離的連結後面加個“問號”,並且不要啟用QSA標誌,就可剝離查詢字串
RewriteEngine On
# Whatever QS is
RewriteCond %{QUERY_STRING} .
# I don't want it with Question mark
RewriteRule foo.php(.*) /foo.php? [L]
四、利用RewriteCond和RewriteRule進行訪問控制
我們在第一篇.htaccess基礎中提到了很多有用的訪問控制方法,其實通過Rewrite也能實現類似的功能,而且可以更強大!
- 檔案訪問控制
之前利用Order、Files及FilesMatch命令實現的訪問控制可以滿足大部分要求,但是當使用者被拒絕時,他們看到的是碩大的“403 Forbidden”,如果你不想傷害使用者的感情,就需要顯示一些別的東西,通過Rewrite就可以實現這個特性:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$
RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$
RewriteCond %{REQUEST_FILENAME} !special.zip$
RewriteRule ^(.+)$ /chat/ [NC]
該規則將僅允許使用者請求.css, .js型別的檔案,還有special.zip檔案
RewriteRule 後面指定了限制規則:對映到/char/目錄下處理
RewriteCond 後面的“感嘆號”(!)起到了“否定”作用,它表明,對不滿足後面正規表示式者應用RewriteRule規則,也就是對當前型別的檔案將不應用規則
RewriteCond 之間是以邏輯“與”連線的,也就是隻有當三個條件都不滿足時才執行RewriteRule
該規則也會限制訪問.htm, .jpg等格式
該規則不可以放在虛擬站點根目錄(/)下,否則會死迴圈
如果是二級目錄,如/test/,那麼傳入RewriteCond的引數是以/test/開始的,因此從(.+)獲得的檔名也含有/test/,讀者必須對此多加小心
要想僅獲得檔名,可以將(.+)替換成([^/]+),並且去掉符號^,如下所示:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !([^/]+)\.css$
RewriteCond %{REQUEST_FILENAME} !([^/]+)\.js$
RewriteRule ^(.+)$ /chat/ [NC]
- 用.htaccess阻止User-agent
什麼是User-agent?User-agent用於瀏覽器向伺服器“自報家門”,更確切的說是所有HTTP客戶端都得用User-agent向伺服器“自報家門”,以便伺服器對不同的客戶端作出不同響應。比如,某站點可能需要對瀏覽器、搜尋引擎crawl還有各類下載工具作出不同的響應。伺服器就是通過所謂的User-agent進行區分的。
如果你的伺服器提供某些資源的下載,那麼你就必須多加小心諸如“迅雷”等下載軟體,因為它們可能把你網站資源吸乾,並且影響你的正常訪客訪問。為此,我們可以利用Rewrite限制某些UA的訪問:
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC]
RewriteRule . abuse.txt [L]
該規則限制“迅雷”客戶端下載資源,並將下載檔案重置到abuse.txt
HTTP_USER_AGENT是Apache的內建變數
2.0.50727是迅雷User-agent的特徵字串
RewriteRule後面的“點”表示“任意URI”,也就是不管請求的是什麼,都輸出abuse.txt
通常,我們不會僅限制一個UA。利用[OR]即可實現對多個UA作出統一處理:
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BlackWidow [NC,OR]
# etc..
RewriteCond %{HTTP_USER_AGENT} ^Net\ Vampire [NC]
RewriteRule . abuse.txt [L]
- 用.htaccess阻止盜鏈(hot-linking)
盜鏈,特別是圖片,是非常可恥的!哪怕將圖片複製到自己伺服器上,也比盜用他人的圖片連結來得光彩!(吐糟完畢)
.htaccess的Rewrite功能可以提供非常簡單、有效的方法阻止這種可恥行為:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?lesca\.me/ [NC]
RewriteCond %{REQUEST_URI} !hotlink\.png [NC]
RewriteRule .*\.(gif|jpg|png)$ /hotlink.png [NC]
簡單解釋一下該規則的功能:
除本站以外其他網站都不得引用本站圖片,具體可以理解為
如果引用站點為“空”或者是“本站”,或者,所引用物件是“hotlink.png”,那麼就允許訪問
再次提醒,RewriteCond之間預設的邏輯連線詞是邏輯“與”
這裡的難點是理解邏輯轉換,即德·摩根定律
References:
[1] more .htaccess tips and tricks..
[2] Stupid htaccess Tricks
[3] QSA Flag
[4] 5 useful url rewriting examples using .htaccess
本文出自 Lesca技術宅,轉載時請註明出處及相應連結。
本文永久連結: http://lesca.me/archives/htaccess-rewrite.html
相關文章
- PHP實現url重寫和.htaccessPHP
- ASP.NET URL Rewrite. URL重寫ASP.NET
- Nginx反向代理中使用proxy_redirect重定向urlNginx
- 利用apache的mod_rewrite做URL規則重寫Apache
- URL重寫(rewrite)的具體實現與異常問題解決
- Rewrite重寫教程前言
- 重定向Redirect 的知識
- 8、flask-Redirect重定向Flask
- Nginx location匹配及Rewrite重寫Nginx
- nginx url重寫Nginx
- ThinkPHP5 利用.htaccess檔案的 Rewrite 規則隱藏URL中的 index.phpPHPIndex
- Discuz X2站點URL靜態化(修改.htaccess檔案設定Rewrite規則)
- 使用htaccess Https到http重定向HTTP
- 淺析物化檢視與查詢重寫(Enable query rewrite)
- 請求轉發與URL重定向
- Nginx實現URL重寫Nginx
- URL 重寫新手指南
- nginx TP5 URL 重寫Nginx
- 【ASP.NET Core】URL重寫ASP.NET
- Nginx實戰(二) URL重寫Nginx
- 使用HttpModule實現URL重寫HTTP
- Document Redirect 與 XHR Redirect區別
- 使用ISAPI_REWRITE限定主機頭做重寫API
- 什麼是SAP CDS重定向檢視(Redirect View)?View
- IIS SSL認證流程& url重寫
- Session,Cookie,jsessionid,Url重寫SessionCookieJS
- 使用 HTTP 模組執行 URL 重寫HTTP
- 請問如何實現URL重寫?
- Apache 重寫規則的常見應用 (rewrite)(轉)Apache
- htaccess RewriteRule 解決多種格式的URL解析
- WebWork 2.2 Filter,Url Rewrite,Servlet規範WebFilterServlet
- Nginx URL重寫規則配置詳解Nginx
- Laravel重寫資源路由自定義URLLaravel路由
- nginx下thinkphp的URL重定向NginxPHP
- 如何 把下面這個url 重寫 用response 重寫到請求中...
- iis6上使用.htaccess檔案,ISAPI_Rewrite的安裝及使用API
- 應用Url重寫時CSS引用問題CSS
- IIS7 asp.net URL重寫配置ASP.NET