深刻理解apache mod_rewrite模塊

mod_rewrite的是什麼?

      mod_rewrite的是一個Apache模塊,可以使服務器操縱請求的網址。根據一系列規則對傳入的網址進行檢查,規則中包含一個正則表達式來檢測特定的格式。 若是在地址中發現了一個格式,而且知足適當的條件,該格式就會被一個替代的字符串或者是動做取代。這一過程一直在進行着,直到沒有更多的規則或是程序被明確告訴中止。

     上面的內容能夠總結爲如下3點:

     *有一個按順序排列的處理規則列表。
     *若是有一個規則相匹配,它會檢查那條規則知足的條件。
     *若是一切都匹配,它會替代或這是作出一個動做。php

mod_rewrite的優勢css

      用這樣的一個地址重定向工具備很明顯的優勢,可是有一些東西也不是很明顯。html

      人們用mod_rewrite的主要緣由是爲了將醜陋的、神祕的網址轉化爲所謂的「友好的地址」或者是「乾淨的地址」。新網址經過多種方式變的友好,而不是僅僅一種。 它們是用戶友好的,表如今可更容易爲人類所理解,瞥一眼就能夠,而且用戶可能本身來操縱網址。做爲額外的獎勵,這些網址對搜索引擎來講也是友好的。建立友好的網址是一個搜索引擎優化技術,網址是一種有效描述他連接的內容的方式。看看下面的例子:面試

  1. 不是很友好: http://example.com/user.php?id=4512  
  2. 比較友好: http://example.com/user/4512/  
  3. 甚至更好:     http://example.com/user/Joe/

      最後的連接不只僅是看上去變的簡單了,它還可使搜索引擎從中提取語義。這種基本的URL重寫機制是使用mod_rewrite的一種方式。然而,正如你將要看到的同樣,除了這些簡單的轉換,它還能夠做不少的事情。

      將同一個例子擴展一下,一些人聲稱經過用mod_rewrite改變你的網址能夠得到安全效益。給出同一個例子,想像,考慮一下下面這個對用戶id的攻擊:正則表達式

  1. http://example.com/user.php?id=AHHHHHH  
  2. http://example.com/user/AHHHHHH/ 

      第一個例子是明確的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目錄中加上如下目錄:

  1. # Only in Apache 1.3  
  2. AddModule mod_rewrite.c  

     然而,這好像在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。

  1. # Redirect everything in this directory to "good.html"  
  2. RewriteEngine on  
  3. RewriteRule .* good.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文件的代碼:

  1. # Enable Rewriting  
  2. RewriteEngine on  
  3.   
  4. # Rewrite user URLs  
  5. #   Input:  user/NAME/  
  6. #   Output: user.php?id=NAME  
  7. RewriteRule ^user/(w+)/?$ user.php?id=$1 

     在我對它作任何解釋以前,我會先講解一下目錄中的另一個文件。

     目錄中包含兩個文件:index.php和user.php。index.php中有一些指向user頁面的連接或者是各類各樣的格式。php代碼用來顯示頁面被請求了,並檢查傳過來的"id"參數。下面是user.php的代碼:

  1. <?php  
  2.   
  3. // Get the username from the url  
  4. $id = $_GET['id'];  
  5.   
  6. ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  
  7.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
  8. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  
  9. <head>  
  10.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>  
  11.     <title>Simple mod_rewrite example</title>  
  12.     <style type="text/css"> .green { color: green; } </style>  
  13. </head>  
  14. <body>  
  15.   <h1>You Are on user.php!</h1>  
  16.   <p>Welcome: <span class="green"><?php echo $id; ?></span></p>  
  17. </body>  
  18. </html> 

       這個例子有一些不一樣的地方。首先,請注意URL重寫必須經過RewriteEngine指令啓用!若是你的htaccess文件要使用重寫規則,應始終包括這行,不然你不能肯定它是否啓用了!做爲一個經驗法則,老是將它包括進去並確保每一個.htaccess文件中你只包含了一個。字符串「on」不區分大小寫,所以,當你在網上看到其餘的例子用的是「On」,這是能夠接受的。

     第一個重寫規則是用來處理user.php頁面的。就像這些註釋說的同樣,咱們正在將友好的網址重寫爲正常的URL格式。爲了作到這一點,當輸入友好的網址時,事實上,咱們將它轉化成了標準的查詢字符串URL。將它分解開,咱們就獲得了:

  1. T規則:  
  2. RewriteRule ^user/(w+)/?$ user.php?id=$1  
  3.   
  4. 匹配模式:  
  5. ^             輸入的開頭
  6. user/          以「user/「開始的請求地址  
  7. (w+)        提取全部的字母,並將提取的結果傳給$1  
  8. /?             可選的斜線 "/"  
  9. $              輸入結束  
  10.   
  11. 替換爲:  
  12. user.php?id=   要用到的字符串.  
  13. $1             上面第一個提取到的字符串。  

     下面是一些例子及對上面每行話的解釋:

User.php
輸入 匹配 提取 輸出 結果
user.php?id=joe No   user.php?id=joe Normal
user/joe Yes joe user.php?id=joe Good
user/joe/ Yes joe user.php?id=joe Good
user/joe/x No   user/joe/x Fail

      所以,第一個例子不會受到重寫規則的影響,而且能夠正常訪問。第二個和第三個例子與重寫規則相匹配,會根據重寫規則被改寫,能夠正常訪問,最後一個例子不符合規則且沒法訪問。服務器沒有用戶目錄,不能試圖找到它。這是預期的結果,由於user/joe/ x是一個沒法訪問的網址!

     這個例子比較容易理解。然而,爲了澄清任何更復雜的事情,就像我如今作的同樣,我必需要花好幾分鐘去注意細節。在下一節中,咱們將舉一個更復雜的例子,這個例子涉及全部重寫的核心內容。

 

      注意:若是這個例子不能在你的機器上運行,多是因爲你的Apache或mod_rewrite 版本與PCRE不兼容。請嘗試着將^user/(w+)/?$改成 ^user/([a-z]+)/?$。 請注意,我沒有使用w的縮寫。若是此版本能夠在你的機器上正確運行,那麼你不要使用正則表達式的縮寫,要使用較長的當量(見上面的正則表達式節)。

執行流程詳情

     重寫規則的執行流程比較簡單,但不是徹底明瞭。所以,我將敘述一下細節。這一切都開始於用於向你的服務器提出請求的時候。他們在瀏覽器地址欄中鍵入網址,他們的瀏覽器將之轉換成一個HTTP請求併發送到服務器,Apache收到這一請求,並將之解析成片段。下面是一個例子:

 

      請注意,每當我提到Apache的變量,我使用了一種奇怪的語法:%{APACHE_VAR}。這是由於它相似於mod_rewrite訪問變量的語法。不過,括號內名字是重要的。

      那麼,mod_rewrites是如何工做的?若是你用的是.htaccess文件,那麼你只需輸入REMOTE_URI部分,但沒有開始的斜線!我以前提到過這個,對大多數剛剛開始用它的人來講,這顯得很混亂。若是你是將它添加到了全局配置文件裏,那麼你應當加上斜線。

 

      爲了說的更具體一點兒,下面是Apache的文檔中對mod_rewrite中「URL部分」的描述:

該模式始終是對請求的URL路徑進行正則表達式匹配(主機名後面的那部分,但在任何以問號爲標誌的顯示查詢字符串的前面)。 Apache文檔

      爲了消除你們的模糊不清的認識,下面用黃色高亮顯示的兩個網址是mod_rewrite在.htaccess文件中的「部分網址」:

      在本節接下來的部分我將利用這兩個網址來描述執行的流程。我將把第一個網址稱爲「綠色」網址,第二個稱爲「藍色」網址。在整個分析中,我還將使用「URL部分」來表示開始處沒有斜線的REMOTE_URI。

 
     對於那些想要100%的區分開這兩中教法的人,我這裏說的URL實際上是URI。一個統一資源標識符(URI)的定義有別於統一資源定位符(URL)。一個URI只是標識資源在哪裏,這意味着存在多個URl能夠指向相同的資源,可是他們是不一樣的地址。一個URI可能在找到資源以前通過了數次跳動和重定向。然而,URL倒是標識資源的確切位置。這種細微的差異隨着時間的推移,變得越來月模糊,以致於沒有人關心它們的差別。我將繼續使用術語URL,由於人們用它更舒服一些。

 
     因此,如今咱們知道重寫規則將要採起行動了。一旦Apache已解析出請求,它就會將它翻譯成它認爲的文件,並去讀取該文件。在這個過程當中,他會搜索.htaccess文件。假設,.htaccess文件起用了RewriteEngine,那麼任何重寫規則均可以更改網址。地址的急劇變化(如Apache將某個網址原來指向的目錄替換爲另一個目錄)將促發Apache發出子請求,進而獲取新的文件。 


      在大多數狀況下,你是能夠看到子請求的。這些實現細節對於瞭解你寫的或使用的大多數簡單的重寫規則來講並不重要。更重要的是知道Apache如何處理.htaccess文件中的重寫規則。

 
      .htaccess文件中的規則會以它們出現的順序被處理。請注意,每一個重寫規則都是「部分網址」,也就是說相似於REMOTE_URI。當一個規則促發替換的時候,修改後的「部分網址」將被移交給下一個規則。這意味着,正在處理的網址可能已經被前面的規則修改過了,網址會被每一個相匹配的規則更新。這一點很重要!

 
      下面是一個流程圖,它試圖提供URL在經過含有多個規則的.htaccess文件時的執行過程:

     請注意,流程圖的頂部的將會與重寫規則進行匹配的數據是「網址部分」,若是替換成功,則修改過的網址會與下一條規則繼續匹配。 


      前面,我介紹了重寫條件,可是沒有詳談。每一個重寫過程都與一條重寫規則相關聯。條件出如今與它們有聯繫的規則以前,可是隻有與規則相匹配了,網址纔會獲得評估。正如流程圖所示,若是與一個重寫規則相匹配了,Apache會檢查這條規則有什麼條件(即作出替換是否須要其餘條件)。若是沒有條件,那麼將進行替代並進入下一步。若是須要條件,那麼只有全部的條件都成立的時候,纔會進行替換。舉一個具體的例子。

 
      我用的網址其實是我放在"profile_example"目錄中的源代碼的一部分。這和前面的例子user.php同樣,但如今有一個profile.php頁面,一個附加的重寫規則,和一個條件!讓咱們看一下這段代碼和它在Apache中的執行過程:

     這裏有兩個規則。規則#1和咱們前面看到的user例子同樣。規則#2是新加的,注意它有一個條件。在「網址部分」咱們已經討論過會從上到下遍歷每一條規則。所以,必須先通過規則#1,而後纔是規則#2。

 
     理解這個例子的關鍵是首先要了解目標。在這個例子中,我容許友好網址,但實際上,我要明確地禁止直接訪問PHP頁面。請注意,有些人可能會說這是一個壞主意。他們可能會說,做爲開發者,這個調試起來會更難。是這樣的,事實上我不推薦作這樣的小把戲,可是做爲一個例子,這很好。更實際的使用mod_rewrite的例子會在本教程後面的部分看到。

 
      所以,在這一點的基礎上,讓咱們看看我綠色網址發生了什麼。此次,咱們但願取得成功。

      在最上面,能夠看到Apache的THE_REQUEST變量。我把它放在上方是由於它不像咱們要處理的其餘Apache變量,在請求期間這個變量的值不會改變。這就是規則#2使用%{THE_REQUEST}的緣由之一。在THE_REQUEST下面,咱們看到綠色的「網址部分」開始進入第一個規則了: 

  • URL匹配成功。
  • 沒有任何條件,所以繼續。
  • 進行替換。
  • 沒有任何標誌,於是繼續。 

      經過第一條規則後,該網址已經更改。網址已被重寫成了profile.php?id=joe,這時,Apache會聽下來更新它的大多數變量。咱們看不到?id=joe,新的「網址部分」會進入下一條規則。這是咱們第一次遇到條件:

  • URL匹配成功。
  • 還有條件,咱們將檢查條件。
  • THE_REQUEST不包含profile.php,所以條件檢查失敗。
  • 由於不知足條件,因此咱們忽略替換和標誌。
  • 這條規則沒有改變URL。

      這一次,咱們經過了全部的重寫規則,而且profile.php?id=joe 頁會被正確的提取。

    
      下面介紹關於如何執行藍色的URL,這一次,咱們要失敗:

    我再次將THE_REQUEST的值放在了最上面,藍色的「網址部分」進入規則#1: 

  • URL匹配失敗。
  • 其餘的一切都被忽略,網址沒有改變,進入下一步。 

     第一個規則很容易。一般狀況下,若是URL匹配失敗,那麼它會原樣進入下一步。如今進入規則#2: 

  • URL匹配成功。
  • 有條件須要比較,所以會先測試條件。
  • 請求包含 profile.php,所以條件測試經過。
  • 經過全部的條件,咱們能夠替換網址了。
  • 」-」是一個特殊的替換,這一爲着任何東西都不會改變了。
  • 規則中有標誌,所以咱們處理標誌。
  • 有一個F標誌,意思是返回一個禁止訪問響應。
  • 一個403 Forbidden響應發送到了客戶端。

     有幾件事情值得再重複一次。爲了使替換髮生,全部條件都必須檢查經過。在上面這種狀況下只有一個條件,而且檢查經過了,因此,能夠對網址進行替換。注意,有一種特殊的替換,不改變任何東西。當你想用標誌作點兒什麼的時候,這種方法至關有用,在這種狀況下,咱們就會這樣作(指的是,替換後什麼都不改變)。

 
     下面是一個URL例子的分解和它們的返回值表:

Profile.php
輸入 匹配 獲取 輸出 結果
profile.php?id=joe Yes (#2)   profile.php?id=joe Forbidden
profile/joe Yes (#1) joe profile.php?id=joe Good
profile/joe/ Yes (#1) joe profile.php?id=joe Good
profile/joe/x No   profile/joe/x Fail

語法

      在介紹重寫規則(RewriteRule)和重寫條件(RewriteCond)的語法以前,我建議你先下載theAddedBytes Cheatsheet。這是由於cheatsheet表列出了最有用的服務器變量,標誌,並有正則表達式技巧,甚至還有幾個例子。在那裏面有這麼多的內容,將它們關聯起來是很難的。 

      讓咱們從重寫規則開始。若是你想作一些特殊的事,你能夠隨時查看Apache的關於重寫規則的文檔。下面是個人概述:

     這個表顯示了什麼類型的標誌是可用的。許多指南涵蓋了flags的詳細講解,我會經過經過下面的例子介紹一下我認爲的用的最多的flag。

 
    下面是Apache的RewriteCond文檔和個人概述:

調試流程

     當你使用mod_rewrite制定新規則的時候,老是以一個簡單的規則開始,而且逐步發展爲最後的版本。歷來不要試圖一會兒將全部的事情辦好。對於重寫條件的編寫,這個道理一樣適用。一次添加規則和條件,屢次測試! 

      我正在介紹的這種方法的關鍵之處是它可讓你知道是否你的一個改變不能正常工做或者是使某個地方運行不正常。當一次作得太多的時候,你會不可避免的遇到錯誤,而且你將不得不恢復你所作的一切更改來找出問題究竟是出在那兒了。這是一項很是艱難的 工做,可能會致使你的失望。不過,若是你老是穩步推動,而且在每一步均可以到達一個能夠正常運行的點,你的處境就會稍好一點兒。


      人們每每忽略這條建議,建立了一個複雜的規則,最終卻不能工做。幾個小時後,他們發現問題沒有出如今複雜的部分,反而只是簡單的正則表達式錯誤,若是他們按我上面解釋的構造規則的換,問題可能早已經被發現了。在反向工程拆解規則上,這種方法也適用。這種作法將極大下降人們的失望!

例子

      在下面的例子中,我老是會假設網站的域名是example.com。此域名很重要,由於它會影響HTTP_HOST變量以及在你的網站上將指定的URL重定向到另外一個文件。若是你打算修改你的任何一個例子,以便它能夠在你的網站上工做,請記住這一點。若是是這樣,只需用你的域名替換「example.com」。例如,Nettuts會將「example.com」改成「nettuts.com」。 


刪除www 

     這是最經典的重寫規則。這將使得每一個經過http://www.example.com訪問你網站的人會獲得一個硬性的重定向,從而其瀏覽器的地址欄中也將進行相應更新。 

  1. RewriteEngine on   
  2. RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]  
  3. RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]  

     這條規則與任何輸入的地址都匹配,並將全部的地址保存爲$1。本例中的重要組成部分是條件語句,這個條件會檢查HTTP_HOST變量,看它是否以「www」開始。若是是這樣,重寫就會發生:

  • 替代的是一個完整的URL (它以http://開始)
  • 替代中包含早期抓取的 $1。
  • [R=301]標誌將瀏覽器重定向到重寫過的網址,在某種意義上說,這是硬性重定向,它是瀏覽器加載新的頁面,並用新的URL地址更新地址欄。
  • [L]標誌的意思是這是最後須要分析的一條規則,重寫引擎應該中止了。

      若是傳入的URL是「http://www.example.com/user/index.html」,那麼HTTP_HOST是beenwww.example.com,重寫會創造http://example.com/user/index.html。 

      若是傳入的URL是「http://example.com/user/index.html」,那麼HTTP_HOST是beenexample.com,不知足條件,重寫引擎將會保持網址不變。 

禁止盜鏈

      盜鏈,在維基百科中被稱爲內聯連接,是用來描述一個網站讀取另外一個網站的內容。一般一個網站,讀取者,將包括一些其餘網站上的媒體文件的連接(讓咱們說成是一個圖像或視頻)——包含內容的主機。在這種狀況下,內容主機的服務器會浪費帶寬爲其餘網站提供內容(譯者注:圖像、視頻等)。 

    對許多人來講,若是其餘網站連接他們的內容,這很好。然而,許多人寧願防止盜鏈,爲了避免支付將本網站內容發送到其餘網站產生的額爲的帶寬。 

     最多見的、基本的防止盜鏈是的方法將一些網站加進空白頁列表,並阻止其餘的一切訪問。你能夠經過檢查引用的內容來找出誰正在從你的網站訪問那些內容。HTTP_REFERER頭(是的它是這樣拼寫的)是由正在訪問資源的瀏覽器或客戶端設置的。最後,這是否是100%可靠的,但它是禁止大多數盜鏈的最有效的方法。所以,你只需驗證引用是否在空白頁列表中。若是引用是不能接受的(空白或其餘人的網站),那麼你能夠給他們發送禁止警告: 

  1. # 給盜鏈着發送403禁止訪問警告。
  2. RewriteEngine on
  3. RewriteCond %{HTTP_REFERER} !^http://example.net/?.*$ [NC]  
  4. RewriteCond %{HTTP_REFERER} !^http://example.com/?.*$ [NC]  
  5. RewriteRule .(gif|jpe?g|png|bmp)$ - [F,NC]  

    在這裏,RewriteRule檢查的是任何一個主流類型的圖像文件,例如的.gif,.png或.jpg。若是你想保護.flv,.swf或者是其餘文件,你能夠添加其餘擴展到這個列表中。 

      被容許訪問的域名是「example.net」和「example.com」,在這兩種狀況下,重寫條件驗證將失敗,替代也不會發生。若是有任何其餘域名嘗試訪問,好比說說「sample.com」企圖訪問,那麼全部的重寫條件會驗證經過,替代會發生,比且[F]禁止動做將被觸發。 

給盜鏈者發送一張警告圖片

     當有人試圖從你的服務器上讀取內容時,前面的例子會返回404禁止訪問警告。實際上,你能夠更進一步,給盜鏈者發送你選擇的任何資源。例如,您能夠發送一個有用的以文字「盜鏈不容許」表述的圖片警告。這樣,其餘人可以意識到他們本身的錯誤,並在他們的主機上保存一份副本。惟一的變化是改變替換方式,並提供一個已經選好的圖片來代替正在被訪問的資源: 
 
  1. # 重定向盜鏈者請求爲 "warning.png"  
  2. RewriteEngine on  
  3. RewriteCond %{HTTP_REFERER} !^http://example.net/?.*$  
  4. RewriteCond %{HTTP_REFERER} !^http://example.com/?.*$   [NC]  
  5. RewriteRule .(gif|jpe?g|png|bmp)$ http://example.com/warning.png [R,NC]   

      注意,這是一個我稱之爲「硬」或「外部」重定向的例子。該重定向規則在他的替換部分有一個URL和一個[R]標誌。 

自定義404 錯誤

    一個竅門:你能夠用htaccess檢查目前的「URL部分」是否是連接到服務器上的實際文件或Web目錄,這是一個建立自定義404「文件未找到」頁面的好方法。例如,若是用戶試圖讀取特定目錄中不存在的頁面時,你能夠重定向它們到任何網頁,如Index頁面或自定義404頁。 

  1. # 顯示「custom_404.html」頁的通用404頁
  2. # 若是請求的頁面不是一個文件或目錄 
  3. #靜態重定向:用戶的地址欄的內容不變。 
  4. RewriteEngine on  
  5. RewriteCond %{REQUEST_FILENAME} !-f  
  6. RewriteCond %{REQUEST_FILENAME} !-d  
  7. RewriteRule .* custom_404.html [L]  

      這是mod_rewrite文件測試的很好的例子。它同bash shell腳本、甚至是Perl腳本文件測試類似。這裏的條件檢查REQUEST_FILENAME是否是一個文件或目錄。在都不是的狀況下,則沒有這樣的文件反饋給這個請求。 

      若是傳入的請求文件沒法找到,那麼返回一個「custom404.html」頁面。注意有沒有[R]標誌,因此這是一個靜態重定向,而不是硬重定向。用戶的地址欄將不會改變,但網頁的內容是「custom404.html」,簡短而簡單。 

安全第一 

     若是你有常用的mod_rewrite代碼片斷,並想輕鬆地分發到其餘的服務器或環境中,你可能得要當心。如前所述,任何一個.htaccess文件的無效指令均可能會引發內部服務錯誤。所以,若是你的代碼片斷要移動到的環境沒有mod_rewrite,你能夠先暫停一下。 

      一個解決這個問題是mod_rewrite模塊的「檢查「指令」,任何一個模塊都有這個指令。只要將你的mod_rewrite代碼放到<IfModule>塊中,你能夠這樣設置: 
 
  1. <IfModule mod_rewrite.c>  
  2.   
  3.   # Turn on  
  4.   RewriteEngine on  
  5.   
  6.   # Always remove www (with a hard redirect)  
  7.   RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]  
  8.   RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]  
  9.   
  10.   # Generic 404 for anyplace on the site  
  11.   # ...  
  12.   
  13. </IfModule>  
結論        我但願本教程可以證實mod_rewrite沒有想象的那麼恐怖,而且事實上經過精心設計,它的複雜性和訪問速度問題均可以免。
相關文章
相關標籤/搜索