將.htm頁面映射到.phphtml
爲何要用重定向?——重定向和URL重寫的區別apache
長短地址轉換數組
去掉www瀏覽器
加上www安全
支持多域名訪問服務器
URL重定向是.htaccess的重頭戲,它能夠將長地址轉爲短地址、將動態地址轉爲靜態地址、重定向丟失的頁面、防止盜鏈、實現自動語言轉換等。筆者以爲難點是在正則表達式的運用和理解上。有關htaccess的正則表達式用法,請查閱本站《.htaccess正則表達式》一文。
實現全部這些神奇功能的模塊叫作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請求,並與以後的規則進行匹配
下面咱們開始講解一些例子。
Options +FollowSymlinks RewriteEngine on RewriteRule ^(.*)\.htm$ $1.php [NC]
注意事項:
該RewriteRule可以將.htm靜態頁面映射到.php動態頁面
若是經過.htm進入,瀏覽器地址欄顯示的是.htm擴展名,但服務器上實際執行的是.php
必須保證服務器上有對應的.php,不然會404
瀏覽器和搜索引擎能夠同時經過.htm和.php訪問網頁
若是該目錄上存在.htm,將被忽略
[NC]表示「不區分大小寫」,更多相似定義請參考本站《.htaccess正則表達式》一文
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也就沒有出現的必要了。
經過重定向,瀏覽器知道頁面位置發生變化,從而改變地址欄顯示的地址
經過重定向,搜索引擎意識到頁面被移動了,從而更新搜索引擎索引,將原來失效的連接從搜索結果中移除
臨時重定向(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
Options +FollowSymlinks RewriteEngine on RewriteCond %{HTTP_HOST} ^www\.(.*) [NC] RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
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]
查詢字符串是指URL請求中「問號」後面的部分。好比,http://mysite/grab?foo=bar中粗體部分就是查詢字符串,其中變量名是foo,值是bar。
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]
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定義的「變量=值」向量(數組)
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]
咱們在第一篇.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]
什麼是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的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之間默認的邏輯鏈接詞是邏輯「與」
這裏的難點是理解邏輯轉換,即德·摩根定律
[1] more .htaccess tips and tricks..
[2] Stupid htaccess Tricks
[3] QSA Flag
[4] 5 useful url rewriting examples using .htaccess