http://lesca.me/archives/htaccess-rewrite.html/comment-page-1#comment-16045
目錄 Table of Contents 一、準備開始: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的重頭戲,它可以將長地址轉為短地址、將動態地址轉為靜態地址、重新導向丟失的頁面、防止盜鏈、實現自動語言轉換等。筆者覺得痛點是在Regex的運用和理解上。有關htaccess的Regex用法,請查閱本站《.htaccessRegex》一文。 一、準備開始: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) 1.將.htm頁面映射到.php
Options +FollowSymlinksRewriteEngine onRewriteRule ^(.*)\.htm$ $1.php [NC]
注意事項: 該RewriteRule能夠將.htm靜態頁面映射到.php動態網頁面 如果通過.htm進入,瀏覽器地址欄顯示的是.htm副檔名,但伺服器上實際執行的是.php 必須保證伺服器上有對應的.php,否則會404 瀏覽器和搜尋引擎可以同時通過.htm和.php訪問網頁 如果該目錄上存在.htm,將被忽略 [NC]表示“不區分大小寫”,更多類似定義請參考本站《.htaccessRegex》一文 2.臨時重新導向(R=302)與永久重新導向(R=301)
RewriteEngine onRewriteBase /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 onRewriteRule ^(.*)$ http://newdomain.com/$1 [R=301,NC,L]
這個規則告訴瀏覽器和搜尋引擎,網站地址發生了永久性變更,使用者的URL請求將會被發送給新的網域名稱(主機)處理。 由於是重新導向到新的主機地址,RewriteBase也就沒有出現的必要了。
3.為什麼要用重新導向。——重新導向和URL重寫的區別 通過重新導向,瀏覽器知道頁面位置發生變化,從而改變地址欄顯示的地址 通過重新導向,搜尋引擎意識到頁面被移動了,從而更新搜尋引擎索引,將原來失效的連結從搜尋結果中移除 臨時重新導向(R=302)和永久重新導向(R=301)都是親搜尋引擎的,是SEO的重要技術 URL重寫用於將頁面映射到本站另一頁面,若重寫到另一網路主機(網域名稱),則按重新導向處理
4.長短地址轉換
利用URL重寫,我們可以很方便地實現長短地址的轉換,但是用重新導向就不合適了。
RewriteEngine OnRewriteRule ^grab /public/files/download/download.php
若訪問
http://mysite/grab?file=my.zip
則會執行該頁面:
http://mysite/public/files/download/download.php?file=my.zip 5.去掉www
Options +FollowSymlinksRewriteEngine onRewriteCond %{HTTP_HOST} ^www\.(.*) [NC]RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
6.加上www
RewriteEngine OnRewriteCond %{HTTP_HOST} ^(.*)$RewriteRule (.*) http://www\.%1/$1 [R=301,L]
7.支援多網域名稱訪問
如果你不湊巧買到了不支援多網域名稱的主機,那麼.htaccess或許可以協助你。現在假設你有網域名稱domain-one.com和domain-two.com,並且在伺服器根目錄有對應檔案夾one和two,那麼通過下面的改寫就能讓Apache同時接受者兩個網域名稱的請求:
#two domains served from one root..RewriteCond %{HTTP_HOST} domain-one.comRewriteCond %{REQUEST_URI} !^/oneRewriteRule ^(.*)$ /one/$1 [L]RewriteCond %{HTTP_HOST} domain-two.comRewriteCond %{REQUEST_URI} !^/twoRewriteRule ^(.*)$ /two/$1 [L]
三、改寫查詢字串QUERY_STRING
查詢字串是指URL請求中“問號”後面的部分。比如,http://mysite/grab?foo=bar中粗體部分就是查詢字串,其中變數名是foo,值是bar。 1.利用QSA轉換查詢字串QUERY_STRING
QSA標誌( Query String Appending)用於在URI中截取查詢字串,這個截取操作是通過小括弧Regex實現的:
RewriteEngine OnRewriteRule /pages/(.+) /page.php?page=$1 [QSA]
將會把請求/pages/123?one=two 映射到 /page.php?page=123&one=two 注意粗體部分幾乎是相同的,除了“問號”變成了“與”符號 如果沒有QSA標誌,那麼會映射到/page.php?page=123。 如果沒有用到小括弧Regex,就不需要QSA,這在上節“長短地址轉換”中已經例證過了。 小括弧Regex可以截取查詢字串中的內容,但是如果沒有開啟QSA標誌,那麼在/page.php?page=$1中“問號”之後將會被剝離丟棄。這種特性可以用於實現“剝離查詢字串”
通過QSA,我們可以將簡單連結/simple/flat/link/ 映射成 server-side.php?first-var=flat&second-var=link
RewriteEngine OnRewriteRule ^/([^/]+)/([^/]+)/? /index.php?first-var=$1&second-var=$2 [QSA]
2.利用RewriteCond改寫查詢字串QUERY_STRING
RewriteEngine OnRewriteCond %{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