mod_rewrite的是什麼?
mod_rewrite的是一個Apache模塊,可以使服務器操縱請求的網址。根據一系列規則對傳入的網址進行檢查,規則中包含一個正則表達式來檢測特定的格式。 若是在地址中發現了一個格式,而且知足適當的條件,該格式就會被一個替代的字符串或者是動做取代。這一過程一直在進行着,直到沒有更多的規則或是程序被明確告訴中止。
上面的內容能夠總結爲如下3點:
*有一個按順序排列的處理規則列表。
*若是有一個規則相匹配,它會檢查那條規則知足的條件。
*若是一切都匹配,它會替代或這是作出一個動做。php
mod_rewrite的優勢css
用這樣的一個地址重定向工具備很明顯的優勢,可是有一些東西也不是很明顯。html
人們用mod_rewrite的主要緣由是爲了將醜陋的、神祕的網址轉化爲所謂的「友好的地址」或者是「乾淨的地址」。新網址經過多種方式變的友好,而不是僅僅一種。 它們是用戶友好的,表如今可更容易爲人類所理解,瞥一眼就能夠,而且用戶可能本身來操縱網址。做爲額外的獎勵,這些網址對搜索引擎來講也是友好的。建立友好的網址是一個搜索引擎優化技術,網址是一種有效描述他連接的內容的方式。看看下面的例子:面試
最後的連接不只僅是看上去變的簡單了,它還可使搜索引擎從中提取語義。這種基本的URL重寫機制是使用mod_rewrite的一種方式。然而,正如你將要看到的同樣,除了這些簡單的轉換,它還能夠做不少的事情。
將同一個例子擴展一下,一些人聲稱經過用mod_rewrite改變你的網址能夠得到安全效益。給出同一個例子,想像,考慮一下下面這個對用戶id的攻擊:正則表達式
第一個例子是明確的PHP腳本調用,而且必須得處理無效的ID號。寫得很差的腳本可能會失敗,更極端的狀況是(寫得很差的Web應用程序)錯誤的輸入可能致使數據損壞。然而,若是隻給用戶顯示友好的網址,也就是說他們甚至不知道user.php網頁的存在,他們可能只知道友好的URL結構。試圖在這種狀況下進行的攻擊可能在讀取PHP腳本以前就已經失敗了。這是由於mod_rewrite的核心是正則表達式的格式匹配。在上面的例子中,你的地址中可能有一個數字,好比( d +),而不是字符,像a-z,當重寫模塊找到的是字母而不是數字時,重寫就會失敗。shell
從安全的角度講,這種額外的抽象功能是不錯的。若是你願意,你甚至能夠防止直接訪問原始PHP腳。不過,咱們決不能使用mod_rewrite來替換通常的安全措施,你的腳本應當在服務器端進行驗證。express
在服務器上啓用mod_rewrite模塊apache
就像啓用.htaccess支持同樣,啓用mod_rewrite或者是其餘apache模塊必須修改全局配置文件(httpd.conf)。就像前面說的同樣,因爲mod_rewrite用的是如此普遍,主機提供商幾乎老是啓用這個模塊的。然而,若是你懷疑你的主機提供商沒有啓用它(咱們會在下面測試),你應當聯繫他們,而且他們很樂意啓用它。瀏覽器
若是你是本身安裝的Apache,毫無疑問,當編譯Apache的時候,要將Mod_rewrite模塊包括進來,由於默認狀況下是不包括它的。然而,它是用的如此廣泛,幾乎全部的安裝指南,包括Apache的安裝文檔都會在他們的示例中指出如何將它編譯進來。然而,預先包裝的版本已經將它啓用了。若是你正在讀這篇文章,那麼你的Apache有99%的可能已經將mod_rewrite模塊編譯進來了,因此你只須進入下一個步驟。安全
若是你是大家網絡的網絡管理員,而且你想確認一下你已經加載了這個模塊,你應當檢查一下httpd.conf文件。在配置文件有很大一部分用於加載那一大堆模塊。下面的行可能會出如今文件中,若是是,好極了!若是它被註釋掉了,或者說是在它前面有一個#號,哪麼你只需將#號刪除掉,留下下面的這一部分:
一、LoadModule rewrite_module modules/mod_rewrite.so
老版本的Apache1.3,可能須要你在LoadModule目錄中加上如下目錄:
然而,這好像在Apache 2及之後的版本中消失了,只須要LoadModule指令。
若是你不得不修改配置文件,那麼你必須重啓你的apache服務。你要記住備份你的原始文件,以防萬一你須要將它還原回之前的版本。
測試mod_rewrite模塊
你能夠經過多種方式測試mod_rewrite模塊是否啓用(或者是工做)了,最簡單的方法是查看PHP的phpinfo函數的輸出。建立下面的這個很是簡單的PHP頁面,在你的瀏覽器中打開它,而且在輸出結果中找一下"mod_rewrite"。
<?php phpinfo(); ?>
mod_rewrite應該會顯示在網頁的「Loaded Modules」部分中,就像這樣:
然而,若是你用的不是PHP(雖然在接下來的教程中我會用它),還有不少方式來測試。Apache有許多命令行工具。
在個人基自己份驗證的第一個教程中,我提到了在htpasswd的工具。你可使用諸如apachectl或者httpd的其餘工具直接對模塊進行測試。有命令行開關可使你檢查現有的已經安裝加載的模塊。您能夠執行下面的命令來獲得一個全部已加載的模塊的列表。 shell> apachectl -t -D DUMP_MODULES 這裏我展現的是這個命令的幫組頁面。而後,我運行了這個命令,並在結果中查找了「rewrite」,有一行輸出與之相匹配。 最後,若是你仍是不能肯定它是否啓用了,像之前同樣將它註釋掉,看看會發生什麼!以後,我會介紹語法,但這裏僅僅是一個測試,看看他是否工做了。下面的.htaccess文件將重定向任何給定的文件夾請求到good.html文件,這意味着若是你的mod_rewrite工做了,你應該看到good.html。若是mod_rewrite不工做,那麼你會看到一個帶警告的index.html。
下面是正確的和錯誤的頁面: .htaccess的內容 一般狀況下,你能夠寫在.htaccess文件中的內容也能夠寫到全局配置文檔中。在mod_rewrite中,若是你將一條規則放的文件不一樣,會有一點兒小差別。最明顯的是: 若是你將【……】規則放到了.htaccess文件中,目錄的前綴(/)在REQUEST_URI變量中會被去掉,由於全部的請求會被自動假設是如今目錄的相對地址。——Apache文檔 有一點要記住,若是你在網上看例子或者是你本身在測試一個實例,要注意前面的斜線!當我將一些例子放到一塊兒的時候,我將在下面試圖澄清這些問題。 正則表達式 本教程不打算教你正則表達式。對於那些你知道的正則表達式,mod_rewrite中用到的正則表達式會根據Apache版本的不一樣而有所改變。在Apache 2.0中,他們彷佛是與Perl兼容(pcre)的正則表達式。這意味着許多你所使用的簡寫,例如w的意思是[A-Za-z0-9],d的意思是[0-9],以及更多不存在的簡寫。可是,個人公司使用的是Apache 1.3,而且Apache1.3的正則表達式是比較有限的。 若是你不知道正則表達式,下面這些有用的教程會讓你快速入門:
還有每一個人都應該知道的一些引用:
若是有尚未花時間去學習正則表達式,我強烈建議你花點時間學習一下。由於一般狀況下,他們沒有你想象的那麼複雜。我從多年的經驗中選擇了上面的那些關於正則表達式的連接,我以爲這些指南對於學習最基礎的東西來講,寫的很好。若是你想有效的利用mod_rewrite,正則表達式是相當重要的,在其餘方面,瞭解他們也頗有用,如在你最喜好的代碼編輯器中使用「查找/替換」。 初次體驗 好了,你等待的耐心已經足夠大了,讓咱們快速的看一個例子。這個例子在連接的源代碼中有。這裏只給出.htaccess文件的代碼:
在我對它作任何解釋以前,我會先講解一下目錄中的另一個文件。 目錄中包含兩個文件:index.php和user.php。index.php中有一些指向user頁面的連接或者是各類各樣的格式。php代碼用來顯示頁面被請求了,並檢查傳過來的"id"參數。下面是user.php的代碼:
這個例子有一些不一樣的地方。首先,請注意URL重寫必須經過RewriteEngine指令啓用!若是你的htaccess文件要使用重寫規則,應始終包括這行,不然你不能肯定它是否啓用了!做爲一個經驗法則,老是將它包括進去並確保每一個.htaccess文件中你只包含了一個。字符串「on」不區分大小寫,所以,當你在網上看到其餘的例子用的是「On」,這是能夠接受的。 第一個重寫規則是用來處理user.php頁面的。就像這些註釋說的同樣,咱們正在將友好的網址重寫爲正常的URL格式。爲了作到這一點,當輸入友好的網址時,事實上,咱們將它轉化成了標準的查詢字符串URL。將它分解開,咱們就獲得了:
下面是一些例子及對上面每行話的解釋:
注意:若是這個例子不能在你的機器上運行,多是因爲你的Apache或mod_rewrite 版本與PCRE不兼容。請嘗試着將^user/(w+)/?$改成 執行流程詳情 重寫規則的執行流程比較簡單,但不是徹底明瞭。所以,我將敘述一下細節。這一切都開始於用於向你的服務器提出請求的時候。他們在瀏覽器地址欄中鍵入網址,他們的瀏覽器將之轉換成一個HTTP請求併發送到服務器,Apache收到這一請求,並將之解析成片段。下面是一個例子:
爲了說的更具體一點兒,下面是Apache的文檔中對mod_rewrite中「URL部分」的描述:
爲了消除你們的模糊不清的認識,下面用黃色高亮顯示的兩個網址是mod_rewrite在.htaccess文件中的「部分網址」: 在本節接下來的部分我將利用這兩個網址來描述執行的流程。我將把第一個網址稱爲「綠色」網址,第二個稱爲「藍色」網址。在整個分析中,我還將使用「URL部分」來表示開始處沒有斜線的REMOTE_URI。
請注意,流程圖的頂部的將會與重寫規則進行匹配的數據是「網址部分」,若是替換成功,則修改過的網址會與下一條規則繼續匹配。
這裏有兩個規則。規則#1和咱們前面看到的user例子同樣。規則#2是新加的,注意它有一個條件。在「網址部分」咱們已經討論過會從上到下遍歷每一條規則。所以,必須先通過規則#1,而後纔是規則#2。 在最上面,能夠看到Apache的THE_REQUEST變量。我把它放在上方是由於它不像咱們要處理的其餘Apache變量,在請求期間這個變量的值不會改變。這就是規則#2使用%{THE_REQUEST}的緣由之一。在THE_REQUEST下面,咱們看到綠色的「網址部分」開始進入第一個規則了:
經過第一條規則後,該網址已經更改。網址已被重寫成了profile.php?id=joe,這時,Apache會聽下來更新它的大多數變量。咱們看不到?id=joe,新的「網址部分」會進入下一條規則。這是咱們第一次遇到條件:
這一次,咱們經過了全部的重寫規則,而且 我再次將THE_REQUEST的值放在了最上面,藍色的「網址部分」進入規則#1:
第一個規則很容易。一般狀況下,若是URL匹配失敗,那麼它會原樣進入下一步。如今進入規則#2:
有幾件事情值得再重複一次。爲了使替換髮生,全部條件都必須檢查經過。在上面這種狀況下只有一個條件,而且檢查經過了,因此,能夠對網址進行替換。注意,有一種特殊的替換,不改變任何東西。當你想用標誌作點兒什麼的時候,這種方法至關有用,在這種狀況下,咱們就會這樣作(指的是,替換後什麼都不改變)。
語法 在介紹重寫規則(RewriteRule)和重寫條件(RewriteCond)的語法以前,我建議你先下載theAddedBytes Cheatsheet。這是由於cheatsheet表列出了最有用的服務器變量,標誌,並有正則表達式技巧,甚至還有幾個例子。在那裏面有這麼多的內容,將它們關聯起來是很難的。 這個表顯示了什麼類型的標誌是可用的。許多指南涵蓋了flags的詳細講解,我會經過經過下面的例子介紹一下我認爲的用的最多的flag。 調試流程 當你使用mod_rewrite制定新規則的時候,老是以一個簡單的規則開始,而且逐步發展爲最後的版本。歷來不要試圖一會兒將全部的事情辦好。對於重寫條件的編寫,這個道理一樣適用。一次添加規則和條件,屢次測試!
例子
這條規則與任何輸入的地址都匹配,並將全部的地址保存爲$1。本例中的重要組成部分是條件語句,這個條件會檢查HTTP_HOST變量,看它是否以「www」開始。若是是這樣,重寫就會發生:
若是傳入的URL是「http://www.example.com/user/index.html」,那麼HTTP_HOST是beenwww.example.com,重寫會創造http://example.com/user/index.html。 盜鏈,在維基百科中被稱爲內聯連接,是用來描述一個網站讀取另外一個網站的內容。一般一個網站,讀取者,將包括一些其餘網站上的媒體文件的連接(讓咱們說成是一個圖像或視頻)——包含內容的主機。在這種狀況下,內容主機的服務器會浪費帶寬爲其餘網站提供內容(譯者注:圖像、視頻等)。
在這裏,RewriteRule檢查的是任何一個主流類型的圖像文件,例如的.gif,.png或.jpg。若是你想保護.flv,.swf或者是其餘文件,你能夠添加其餘擴展到這個列表中。
注意,這是一個我稱之爲「硬」或「外部」重定向的例子。該重定向規則在他的替換部分有一個URL和一個[R]標誌。 自定義404 錯誤
這是mod_rewrite文件測試的很好的例子。它同bash shell腳本、甚至是Perl腳本文件測試類似。這裏的條件檢查REQUEST_FILENAME是否是一個文件或目錄。在都不是的狀況下,則沒有這樣的文件反饋給這個請求。 若是傳入的請求文件沒法找到,那麼返回一個「custom404.html」頁面。注意有沒有[R]標誌,因此這是一個靜態重定向,而不是硬重定向。用戶的地址欄將不會改變,但網頁的內容是「custom404.html」,簡短而簡單。 安全第一 若是你有常用的mod_rewrite代碼片斷,並想輕鬆地分發到其餘的服務器或環境中,你可能得要當心。如前所述,任何一個.htaccess文件的無效指令均可能會引發內部服務錯誤。所以,若是你的代碼片斷要移動到的環境沒有mod_rewrite,你能夠先暫停一下。 一個解決這個問題是mod_rewrite模塊的「檢查「指令」,任何一個模塊都有這個指令。只要將你的mod_rewrite代碼放到<IfModule>塊中,你能夠這樣設置:
|