Apache運維中常用功能配置筆記梳理

散盡浮華發表於2018-10-16

 

Apache 是一款使用量排名第一的 web 伺服器,LAMP 中的 A 指的就是它。由於其開源、穩定、安全等特性而被廣泛使用。下邊記錄了使用 Apache 以來經常用到的功能,做此梳理,作為日常運維筆記所用。

一、Apache的工作模式
Apache 目前一共有三種MPM 模式(多程式處理模組),它們分別是prefork、worker、enent,主要用到前兩種工作模式,且預設的工作模式是prefork。可以通過 httpd -V 來檢視。

[root@uatweb01 ~]# /usr/local/apache/bin/httpd -V | grep -i "server mpm"    
Server MPM:     prefork

編譯的時候,可以通過 configure 的引數來指定:

--with-mpm=prefork|worker|event

1)prefork 工作模式
Apache在啟動之初,就預先fork一些子程式,然後等待請求進來。之所以這樣做,是為了減少頻繁建立和銷燬程式的開銷。每個子程式只有一個執行緒,在一個時間點內,只能處理一個請求。
優點:成熟穩定,相容所有新老模組。同時,不需要擔心執行緒安全的問題。
缺點:一個程式相對佔用更多的系統資源,消耗更多的記憶體。而且,它並不擅長處理高併發請求。

2)worker 工作模式
使用了多程式和多執行緒的混合模式。它也預先fork了幾個子程式(數量比較少),然後每個子程式建立一些執行緒,同時包括一個監聽執行緒。每個請求過來,會被分配到1個執行緒來服務。執行緒比起程式會更輕量,因為執行緒通常會共享父程式的記憶體空間,因此,記憶體的佔用會減少一些。在高併發的場景下,因為比起prefork有更多的可用執行緒,表現會更優秀一些。
優點:佔據更少的記憶體,高併發下表現更優秀。
缺點:必須考慮執行緒安全的問題。

3)event 工作模式
它和worker模式很像,最大的區別在於,它解決了keep-alive場景下,長期被佔用的執行緒的資源浪費問題。event MPM中,會有一個專門的執行緒來管理這些keep-alive型別的執行緒,當有真實請求過來的時候,將請求傳遞給服務執行緒,執行完畢後,又允許它釋放。這樣增強了高併發場景下的請求處理能力。

HTTP採用keepalive方式減少TCP連線數量,但是由於需要與伺服器執行緒或程式進行繫結,導致一個繁忙的伺服器會消耗完所有的執行緒。Event MPM是解決這個問題的一種新模型,它把服務程式從連線中分離出來。在伺服器處理速度很快,同時具有非常高的點選率時,可用的執行緒數量就是關鍵的資源限 制,此時Event MPM方式是最有效的,但不能在HTTPS訪問下工作。

二、Apache的使用者認證
有時候,需要給apache一些特殊的訪問設定一個使用者認證機制,增加安全。比如公司網站,一般都是有一個管理後臺的,雖然管理後臺本身就有密碼,但為了更加安全,可以再設定一層使用者認證。

1)編輯配置檔案)
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
 
在對應的虛擬主機配置中加入如下配置:
<VirtualHost *:80>
    DocumentRoot "/usr/local/apache2/htdocs"
ServerName www.kevin.com
ServerAlias www.bobo.com
    <Directory /usr/local/apache2/htdocs/>
        AllowOverride AuthConfig
        AuthName "Please input you acount."
        AuthType Basic
        AuthUserFile /usr/local/apache2/htdocs/.htpasswd
        require valid-user
    </Directory>
</VirtualHost>
 
說明:首先指定要對哪個目錄進行驗證,AuthName自定義,AuthUserFile指定使用者密碼檔案在哪裡。
 
2)建立加密用的使用者名稱和密碼檔案)
# htpasswd -c /usr/local/apache2/htdocs/.htpasswd liwei
# htpasswd -m /usr/local/apache2/htdocs/.htpasswd admin
 
建立第一個使用者時-c選項建立.htpasswd檔案,-m選項增加使用者,根據提示輸入密碼。
 
3)重啟apache服務
# apachectl -t
# apachectl graceful
 
先檢查配置是否正確,然後用graceful相當於是reload配置,不用重啟apache服務,效果一樣。
如上配置後,通過瀏覽器輸入網址,訪問就會提示輸入密碼。

========================================================
在子目錄中放寬安全限制
也就是說,比如我們現在已經在/usr/local/apache2/htdocs/這個目錄上加上了使用者名稱和密碼的認證。
但如果想在/usr/local/apache2/htdocs/php這個目錄中不需要認證,使使用者可以直接訪問。
要達到上面的要求,就需要在配置檔案中加入:
  
<Directory "/usr/local/apache2/htdocs/php">
Satisfy Any
Order Deny,Allow
Allow from all
</Directory>
  
或者:
  
在/usr/local/apache2/htdocs/php目錄下建立.htaccess檔案,把
Satisfy Any
Order Deny,Allow
Allow from all

=================================================
如果已經限制了一個目錄的訪問,需要使用者名稱和密碼,但想要放開這個目錄中的其中一個檔案(例如:back.html)
的許可權,使其可以任意訪問,在配置檔案中新增:
  
<Files back.html>
Satisfy Any
Order Deny,Allow
Allow from all
</Files>

=================================================
檢視通過驗證的使用者名稱稱:
可以檢視REMOTE_USER環境變更。在access_log中也可以看到。

=================================================
禁止通過代理伺服器訪問特定的URL

<Directory proxy:http://192.168.10.10/music/>
Order Allow,Deny
Deny from all
Satisfy All
</Directory>
  
上述方法都無法滿足要求時,可以使用正規表示式的方式,使用Rewrite指令。

================================================
想拒絕所有對目錄中檔案的訪問,除了特殊指定副檔名的檔案(比如.html檔案)

<Directory "/usr/local/apache2/htdocs/test">
Satisfy all
Order Allow,Deny
Deny from all
        <Files *.html>
          Order Deny,Allow
          Allow from all
          Satisfy any
        </Files>
</Directory>
  
以上指令,使得test目錄及其子目錄下的所有非.html檔案無法訪問,只有.html的檔案可以訪問。

三、設定預設虛擬主機
預設虛擬主機就是配置檔案裡的第一個虛擬主機。關於預設虛擬主機有個特點,凡是解析到這臺伺服器的域名,不管是什麼域名,只要在配置檔案中沒有配置,那麼都會訪問到這個主機上來。如果直接用IP訪問,會訪問到這個站點上來。為了避免別人亂解析,所以應該把預設也就是第一個虛擬主機給禁止掉。使用allow,deny語句就可以禁止掉了。

1)配置預設虛擬主機
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
 
新增一個虛擬主機的記錄:
<VirtualHost *:80>
    DocumentRoot "/data/www"
    ServerName www.kevin.com
    <Directory /data/www>
        Order allow,deny
        Deny from all
    </Directory>
</VirtualHost>
 
建立/data/www目錄,並且設定600許可權,daemon使用者無法訪問:
 
# mkdir /data/www
# chmod -R 600 /data/www
 
2)重啟apache伺服器
# apachectl -t
# apachectl graceful
 
如果用IP或其它解析的域名訪問,發現提示:
Forbidden
You don't have permission to access / on this server.

=================================================
只有一個IP,但想在系統上支援多個網站:
  
NameVirtualHost *
<VirtualHost *:80>
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/www.kevin.com
    ServerName www.kevin.com
    ServerAlias www.bobo.com                    ######p這條指令可對虛擬主機設定多個名稱
    ErrorLog logs/www.kevin.com-error_log
    CustomLog logs/www.kevin.com-access_log common
</VirtualHost>
  
其中:
"*" 表示所設定的主機可在所有的地址上執行。對於只有單一地址的機器,這表示會在該地址上執行,同時也會在loopback地址上執行。
如果NameVirtualHost 後面放置主機名稱可能會在啟動伺服器時停用虛擬主機的機制。
虛擬主機會使使用者無法再訪問配置檔案中的主伺服器。如果想讓主伺服器成為預設伺服器,則必須在虛擬主機區塊中先將它列出。
對於每個虛擬主機名稱,還需要在DNS中新增相關記錄。

=================================================
# /usr/local/apache2/bin/httpd -S    顯示虛擬主機的配置

=================================================
ErrorDocument 404 /err.html    這個指令可以讓沒有打到指定網頁的時候,不顯示404錯誤,而是err.html頁面。
錯誤號可以是其它的號碼,如403、500等
  
例如:
<VirtualHost *>
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/kevin.com
    ServerName kevin.com
    ErrorLog logs/kevin.com-error_log
    CustomLog logs/kevin.com-access_log combined
    ErrorDocument 404 /err.html
</VirtualHost>
  
根據以上配置,訪問kevin.com/index.html時,如果/www/docs/kevin.com目錄下沒有index.html檔案時,
則會顯示/www/docs/kevin.com目錄下的err.html檔案

=================================================
如果是有多個IP的情況下,想在每個地址上支援一個網站:
  
NameVirtualHost 127.0.0.1
<VirtualHost 172.16.50.230>
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/bobo.bobo.com
    ServerName bobo.bobo.com
    ErrorLog logs/bobo.bobo.com-error_log
    CustomLog logs/bobo.bobo.com-access_log combined
</VirtualHost>

<VirtualHost 172.16.50.231>
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/kevin.com
    ServerName kevin.com
    ErrorLog logs/kevin.com-error_log
    CustomLog logs/kevin.com-access_log combined
</VirtualHost>
  
以上配置根據所訪問的IP地址不同,會訪問不同的虛擬主機。如果伺服器上還有其它的IP地址,但是沒有在配置檔案的虛擬主機區塊列出來時,
這時訪問這個其它的IP地址,請求會被送至在配置檔案主設定區的虛擬主機

=================================================
建立以IP定址的預設虛擬主機,以配置檔案中加入下面程式碼:
  
<VirtualHost _default_>
    DocumentRoot /www/htdocs
    ErrorDocument 404 /err.html
</VirtualHost>
  
加入以上程式碼後,如果訪問本地的IP,但是該IP確沒有在配置檔案中配置時,則會訪問以上程式碼指定的頁面

=================================================
混用以IP定址及以名稱定址虛擬主機:
  
ServerName 127.0.0.1
NameVirtualHost 172.16.50.10
NameVirtualHost 172.16.50.230
<VirtualHost 172.16.50.10>                             ################此處不同
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/kevin.com
    ServerName kevin.com                                   ################此處不同
    ErrorLog logs/kevin.com-error_log
    CustomLog logs/kevin.com-access_log combined
</VirtualHost>
<VirtualHost 172.16.50.230>                            ################此處不同
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/kevin.com
    ServerName kevin.bobo.com                          ################此處不同
    ErrorLog logs/kevin.bobo.com-error_log
    CustomLog logs/kevin.bobo.com-access_log combined
</VirtualHost>
<VirtualHost 172.16.50.230>                          ################此處不同
    ServerAdmin webmaster@www.kevin.com
    DocumentRoot /www/docs/kevin.com
    ServerName bobo.bobo.com                          ################此處不同
    ErrorLog logs/bobo.bobo.com-error_log
    CustomLog logs/bobo.bobo.com-access_log combined
</VirtualHost>

=================================================
mod_vhost_alias   模組可以建立大量的虛擬主機

=================================================
將URL對應至特定目錄。比如說:
訪問http://172.16.50.10/bobo,如果不想讓它訪問/usr/local/apache2/htdocs/bobo,
而是讓它訪問其它的目錄中的內容,可以在配置檔案中加入如下:
Alias /bobo /home/bobo/apache_bobo
  
然後還要把指定的目錄加入到配置檔案中,以讓apache可以訪問,預設情況下apache是不訪問DocumentRoot以外的目錄的。
<Directory "/home/bobo/apache_bobo">
    Order allow,deny
    Allow from all
</Directory>
  
這種用Alias的目錄指定,其實是用Alias的第二個引數去替換第一個引數。
本例中就是用/home/bobo/apache_bobo去替換/bobo
因此,我們訪問http://172.16.50.10/bobo
其實上是訪問http://172.16.50.10/home/bobo/apache_bobo
  
這種方法對"/"符號要求非常嚴格,如果上例我們寫成Alias /bobo/ /home/bobo/apache_bobo,
而我們在訪問http://172.16.50.10/bobo/index.html,其實是訪問http://172.16.50.10/home/bobo/apache_boboindex.html,
這是錯誤的,因為/home/bobo/apache_bobo替換的是/bobo/,
注意,這裡把最後的“/”也替換了,所以轉換後就是前面所說那樣錯誤的URL。
  
Alias也可以為現有的網頁內容建立新的URL,例如要想原來http://172.16.50.10/php/phpinfo.php內容,
通過http://172.16.50.10/newphp/phpinfo.php也可以訪問,
只要在配置檔案中加入如下一行:
Alias /newphp /usr/local/apache2/htdocs/php
  
Alias隻影響本地URI,不會影響URL的主機名部分。

四、域名301跳轉
一個站點難免會有多個域名,而多個域名總得有一個主次,比如我的網站可以用兩個域名訪問:www.kevin.cn 和 www.bobo.cn 但大家發現不管我用哪個域名訪問,最終都會跳轉到www.bobo.con 上來。這個行為就叫做域名跳轉,這裡的301只是一個狀態碼,跳轉除了301還有302,301是永久跳轉,302是臨時跳轉,網站上一定要設定為301,這樣對搜尋引擎是比較友好的。

1)配置域名跳轉
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^www.abc.com$
    RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]
</IfModule>

配置為:當訪問abc時,跳轉到123的網站。

2)配置多個域名跳轉

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^www.abc.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.abcd.com$
    RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]
</IfModule>

3)重啟伺服器並測試
# apachectl -t
# apachectl graceful

4)測試:
# curl -x 192.168.0.8:80  www.abc.com -I
HTTP/1.1 301 Moved Permanently
Date: Tue, 25 Oct 2016 15:48:10 GMT
Server: Apache/2.2.31 (Unix) PHP/5.5.38
Location: http://www.123.com/
Content-Type: text/html; charset=iso-8859-1

# curl -x 192.168.0.8:80  www.abcd.com -I
HTTP/1.1 301 Moved Permanently
Date: Tue, 25 Oct 2016 15:48:49 GMT
Server: Apache/2.2.31 (Unix) PHP/5.5.38
Location: http://www.123.com/
Content-Type: text/html; charset=iso-8859-1

通過上述測試,發現無論是abc或abcd都可以跳轉到 www.123.com 域名上來,通過瀏覽器訪問也一樣。

五、Apache日誌

指定日誌記錄格式,組合日誌格式(combined)或通用日誌格式(common),修改配置檔案:
CustomLog logs/access_log combined    組合日誌格式
CustomLog logs/access_log common      通用日誌格式

通用日誌格式與組合日誌格式的"%h"控制符表示遠端請求使用者的身份,依據HostNameLookups指令的設定值,
可能是主機名也可能是IP地址。
如果想永遠記錄IP地址,則使用“%a”控制符。

記錄從客戶端收到的cookie
CustomLog logs/cookies_in.log "%{UNIQUE_ID}e %{Cookie}i"
CustomLog logs/cookies2_in.log "%{UNIQUE_ID}e %{Cookie2}i"
  
記錄由伺服器設定並傳送給客戶端的cookie值:
CustomLog logs/cookies_out.log "%{UNIQUE_ID}e %{Set-Cookie}o"
CustomLog logs/cookies2_out.log "%{UNIQUE_ID}e %{Set-Cookie2}o"

不記錄來自本機網頁的影象請求:
<FilesMatch \.(jpg|gif|png$)>
SetEnvIfNoCase Referrer "^http://www.kevin.com/" local_referrer=1
</FilesMatch>
Customlog logs/access_log combined env=!local_referrer

按照日或小時來記錄請求:
CustomLog "| /usr/local/apache2/bin/rotatelogs /usr/local/apache2/logs/access_log.%Y-%m-%d 86400" combined
  
其中:
rotatelogs的第一個引數是主日誌檔名如果有%字元,則表示日誌檔名中時間的格式,如果沒有指定時間格式,則是以秒為單位,
從1970.1.1日算起的秒數
第二個引數是產生新日誌的間隔是多少秒。也可以是大小如果把上例中的86400換成5M,則表時日誌達到5M時,就會產生一個新的日誌,
日誌的名字是access_log.%Y-%m-%d格式的

logresolve 將日誌中記錄的IP地址解析為主機名
例如:
# logresolve -c < /usr/local/apache2/logs/access_log.raw > access_log.resolved
  
也可以讓apache在處理過程中使用IP地址,然後在記錄日誌時,以管道方式的日誌記錄程式來解析,修改配置檔案:
HostnameLookups off
CustomLog "|/usr/local/apache2/bin/logresolve -c >> /usr/local/apache2/logs/access_log.resolved" combined

Apache日誌切割
每訪問一次網站,那麼就會記錄若干條日誌。當然前提是已經設定了日誌,日誌不去管理,時間長了日誌檔案會越來越大,如何避免產生這麼大的日誌檔案?其實apache有相關的配置,使日誌按照我們的需求進行歸檔,比如每天一個新日誌,或者每小時一個新的日誌。

1)首先簡單設定日誌的路徑名稱
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf

ErrorLog "logs/error.log"
CustomLog "logs/access.log" combined
 
指定了日誌存放在/usr/local/apache2/logs目錄下分別為error.log和access.log,combined為日誌顯示的格式,
日誌格式可以參考配置檔案httpd.conf中格式的指定,如下:
 
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
 
2)設定apache日誌分割
同樣編輯配置檔案httpd-vhosts.conf
 
ErrorLog "|/usr/local/apache2/bin/rotatelogs -l /usr/local/apache2/logs/aaa-error_%Y%m%d.log 86400"
CustomLog "|/usr/local/apache2/bin/rotatelogs -l /usr/local/apache2/logs/aaa-access_%Y%m%d.log 86400" combined
 
ErrorLog是錯誤日誌,CustomLog是訪問日誌。|就是管道符,意思是把產生的日誌交給rotatelog這個工具,而這個工具就是apache自帶的切割日誌的工具。
-l 的作用是校準時區為UTC,也就是北京時間。86400,單位是秒,正好是一天,那麼日誌會每天切割一次。而最後面的combined為日誌的格式,在httpd.conf中有定義。

Apache不記錄指定檔案型別的日誌
如果一個網站訪問量特別大,那麼訪問日誌就會很多,但有一些訪問日誌我們其實是可以忽略掉的,比如網站的一些圖片,還有js、css等靜態物件。而這些檔案的訪問往往是巨量的,而且即使記錄這些日誌也沒有什麼用,那麼如何過濾掉(不記錄)這些日誌呢?

配置日誌不記錄圖片的訪問
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
 
相關配置為:
SetEnvIf Request_URI ".*\.gif$" image-request
SetEnvIf Request_URI ".*\.jpg$" image-request
SetEnvIf Request_URI ".*\.png$" image-request
SetEnvIf Request_URI ".*\.bmp$" image-request
SetEnvIf Request_URI ".*\.swf$" image-request
SetEnvIf Request_URI ".*\.js$"  image-request
SetEnvIf Request_URI ".*\.css$" image-request
CustomLog "|/usr/local ... _%Y%m%d.log 86400" combined env=!image-request
 
說明:
在原來日誌配置基礎上,增加了一些image-request的定義,比如把gif、jpg、bmp、swf、js、css等結尾的全標記為image-request,
然後在配置日誌後加一個標記env=!image-request,表示取反。

六、Apache配置靜態快取
所說的靜態檔案指的是圖片、js、css等檔案,使用者訪問一個站點,其實大多數元素都是圖片、js、css等,這些靜態檔案其實是會被客戶端的瀏覽器快取到本地電腦上的,目的就是為了下次再請求時不再去伺服器上下載,這樣就加快了速度,提高了使用者體驗。但這些靜態檔案總不能一直快取,它總有一些時效性,那麼就得設定這個過期時間。

1)配置靜態快取
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf

<IfModule mod_expires.c>
    ExpiresActive on
    ExpiresByType image/gif "access plus 1 days"
    ExpiresByType image/jpeg "access plus 24 hours"
    ExpiresByType image/png "access plus 24 hours"
    ExpiresByType text/css "now plus 2 hour"
    ExpiresByType application/x-javascript "now plus 2 hours"
    ExpiresByType application/javascript "now plus 2 hours"
    ExpiresByType application/x-shockwave-flash "now plus 2 hours"
    ExpiresDefault "now plus 0 min"
</IfModule>


或者使用 mod_headers 模組實現:

<IfModule mod_headers.c>
    # htm,html,txt 類的檔案快取一個小時
    <filesmatch "\.(html|htm|txt)$">
        header set cache-control "max-age=3600"
    </filesmatch>
    
    # css, js, swf 類的檔案快取一個星期
    <filesmatch "\.(css|js|swf)$">
        header set cache-control "max-age=604800"
    </filesmatch>
    
    # jpg,gif,jpeg,png,ico,flv,pdf 等檔案快取一年
    <filesmatch "\.(ico|gif|jpg|jpeg|png|flv|pdf)$">
        header set cache-control "max-age=29030400"
    </filesmatch>
</IfModule>

說明:
這裡的時間單位可以 days、 hours 甚至是 min,兩種不同的方法,上面使用的是mod_expires,
而下面用的是 mod_headers,要想使用這些模組,必須要事先已經支援。如何檢視是否支援,使用命令:

# /usr/local/apache2/bin/apachectl -M

2)重啟伺服器並驗證
# apachectl -t
# apachectl graceful

3)驗證:
# curl -x127.0.0.1:80 'http://www.kevin.com/static/image/common/online_admin.gif' -I
HTTP/1.1 200 OK
Date: Wed, 26 Oct 2016 03:51:26 GMT
Server: Apache/2.2.31 (Unix) PHP/5.5.38
Last-Modified: Tue, 31 May 2016 03:08:36 GMT
ETag: "46891b-16b-5341ab0597500"
Accept-Ranges: bytes
Content-Length: 363
Cache-Control: max-age=86400
Expires: Thu, 27 Oct 2016 03:51:26 GMT
Content-Type: image/gif

七、Apache配置防盜鏈
盜鏈,全稱是盜取連結,假如我們的網站有很多好看的圖片,別人可以檢視我們網站圖片的連結,然後應用在他的網站上,這樣的話,去訪問他的網站,實際上消耗的是我們的流量(因為實際連結在我們這裡),這樣我們就不得不去配置防盜鏈,使得別人不能複製我們圖片的連結。

防盜鏈的實現原理就不得不從HTTP協議說起,在HTTP協議中,有一個表頭欄位叫referer,採用URL的格式來表示從哪兒連結到當前的網頁或檔案。換句話說,通過referer,網站可以檢測目標網頁訪問的來源網頁,如果是資原始檔,則可以跟蹤到顯示它的網頁地址。有了referer跟蹤來源就好辦了,
這時就可以通過技術手段來進行處理,一旦檢測到來源不是本站即進行阻止或者返回指定的頁面。

如果想對自己的網站進行防盜鏈保護,則需要針對不同的情況進行區別對待。如果網站伺服器用的是apache,那麼使用apache自帶的Url Rewrite功能可以很輕鬆地防止各種盜鏈,其原理是檢查refer,如果refer的資訊來自其他網站則重定向到指定圖片或網頁上。

如果網站有很多漂亮的圖片,比如網站域名 www.kevin.com,圖片地址為 www.kevin.com/image/111.jpg,那麼其它人就可以直接把這個地址放到他
自己的網站上,他的使用者可以直接從他網站檢視這張圖片,而實際圖片是從你的網站訪問的,所產生的頻寬消耗對你沒有任何意義,應該對這些圖片限制一下,
凡是在第三方站點上,嚴禁訪問你站點的圖片,如何配置呢?

# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf

SetEnvIfNoCase Referer "^http://.*\.kevin\.com" local_ref
SetEnvIfNoCase Referer ".*\.abc\.com" local_ref
SetEnvIfNoCase Referer "^$" local_ref
<filesmatch "\.(txt|doc|mp3|zip|rar|jpg|gif)">
    Order Allow,Deny
    Allow from env=local_ref
</filesmatch>
 
說明:
在這段配置中涉及到一個名詞referer,其實就是上次訪問的網站連結。配置referer是根據來源連結做限制的,
如果來源連結不是我們想要的,就直接拒絕,這就是防盜鏈的原理。當然不止是圖片,mp3、rar、zip等檔案同樣支援。
上述配置中預設是除了定義的列表中的referer,其它都拒絕。

Directory表示指定哪個目錄,我們設定防盜鏈肯定是針對本站點,所以直接寫站點。
SetEnv開頭的是referer的白名單
local_ref    表示空的Refer
filesmatch開頭的指的後面這些格式的檔案不設定白名單,(就是說針對這些檔案做防盜鏈)
order定義訪問控制的,order定義順序,是先允許還是先拒絕。
allow一行的意思是把上面末尾帶有local_ref的白名單referer做一個允許。其他的使用上一行的order給deny掉

然後儲存檢查錯誤,然後重啟。
# apachectl -t
# apachectl graceful


再看之前用到的一例:
<Directory /data/wwwroot/boke>
        SetEnvIfNoCase Referer "http://kevin.com"; local_ref
        SetEnvIfNoCase Referer "http://xiaobo.com"; local_ref
        SetEnvIfNoCase Referer "^$" local_ref                        
        <filesmatch "\.(txt|doc|mp3|zip|rar|jpg|gif)">
            Order Allow,Deny
            Allow from env=local_ref
        </filesmatch>
 </Directory>


來做一個測試,測試一下http://kevin.com/ai.png瀏覽器看看能不能開啟,或者把它以超連結的形式發到論壇,然後點開。
發現點開後出現"Forbidden"的報錯頁面,這種情況就是空referer,就是防盜鏈起了作用!

八、Apache訪問控制
其實可以對apache的訪問進行控制,可以設定白名單或黑名單(通過allow和deny的規則來配置)。

1)示例一
Order deny,allow
deny from all
allow from 127.0.0.1
 
判斷依據是這樣的:
看Order後面的,哪個在前,哪個在後
如果deny在前,那麼就需要看deny from這句,然後看allow from這句
規則是一條一條匹配的,不管是deny在前還是allow在前,都會生效的。
 
2)示例二
Order allow,deny
deny from all
allow from 127.0.0.1
 
這個就會deny所有了,127.0.0.1也會被deny。因為順序是先allow然後deny,雖然開始allow了127,但是後面又拒絕了它。
 
3)示例三
Order allow,deny
deny from all
 
上面的規則就表示,全部都不能通過。
 
4)示例四
Order deny,allow
deny from all
 
上面的規則表示,全部都不能通。
 
Order deny,allow
只有順序,沒有具體規則,表示全部都可以通行(預設的),因為allow在最後了。
 
Order allow,deny
這個表示,全部都不能通行(預設的),因為deny在最後。
 
5)針對某個目錄限制
比如這個目錄很重要,只允許我們公司的IP訪問,當然這個目錄可以是網站根目錄,也就是整個站點。
<Directory /usr/local/apache2/htdocs>
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</Directory>
 
6)針對請求的URL去限制
<filesmatch "(.*)admin(.*)">
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</filesmatch>
 
這裡用到了filesmatch語法,表示匹配的意思。
 
驗證
# curl -x 192.168.0.8:80 www.kevin.com/admin.php -I
HTTP/1.1 403 Forbidden
Date: Wed, 26 Oct 2016 06:24:54 GMT
Server: Apache/2.2.31 (Unix) PHP/5.5.38
Content-Type: text/html; charset=iso-8859-1
 
# curl -x 127.0.0.1:80 www.kevin.com/admin.php -I
HTTP/1.1 401 Authorization Required
Date: Wed, 26 Oct 2016 06:25:03 GMT
Server: Apache/2.2.31 (Unix) PHP/5.5.38
WWW-Authenticate: Basic realm="Please input you acount."
Content-Type: text/html; charset=iso-8859-1

7)Apache防盜鏈主要是防止本網站的連結被別人盜用。可以使用Apache訪問控制,禁用來源IP訪問
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf

<VirtualHost *:80>
...........
    <Directory "/data/www">
        AllowOverride None
        Options None
        Order allow,deny
        Allow from all                                               #允許所有訪問
        Deny from 127.0.0.1                                     #禁用127.0.0.1訪問
    </Directory>
...........
</VirtualHost>

測試
# curl -x 127.0.0.1:80 -I www.kevin.com                 #127.0.0.1被禁止訪問
HTTP/1.1 403 Forbidden
Date: Wed, 02 Oct 2018 02:47:23 GMT
Server: Apache/2.2.31 (Unix) PHP/5.4.45
Content-Type: text/html; charset=iso-8859-1

# curl -x 192.168.101.230:80 -I www.kevin.com      #192.168.101.230正常訪問
HTTP/1.1 301 Moved Permanently
Date: Wed, 02 Oct 2018 02:47:42 GMT
Server: Apache/2.2.31 (Unix) PHP/5.4.45
X-Powered-By: PHP/5.4.45
location: forum.php
Cache-Control: max-age=0
Expires: Wed, 02 Oct 2018 02:47:42 GMT
Content-Type: text/html

# curl -x 192.168.101.230:80 -I www.kevin.com/forum.php      #正常訪問
HTTP/1.1 200 OK


8)如果希望白名單限制管理員登入網頁URI:http://www.kevin.com/xiaobo.php,怎麼做?)
<VirtualHost *:80>
........
   <filesmatch "(.*)xiaobo(.*)">
        Order deny,allow
         Deny from all                         #禁用所有訪問
         Allow from 127.0.0.1              #允許127.0.0.1訪問  
         Allow from 192.168.101.230
   </filesmatch>

...........
</VirtualHost>

重啟Apache服務後,用PC機器(192.168.101.175)訪問http://www.kevin.com/xiaobo.php,報錯403Forbidden。
# curl -x 192.168.101.230:80 -I http://www.kevin.com/xiaobo.php
HTTP/1.1 200 OK                    200,但是192.168.101.230可以正常訪問

九、禁止解析PHP
某個目錄下禁止解析PHP,這個很有作用,我們做網站安全的時候,這個用的很多,比如某些目錄可以上傳檔案,為了避免上傳的檔案有木馬,所以我們禁止這個目錄下面的訪問解析PHP。

配置禁止解析php

<Directory /usr/local/apache2/htdocs/data>
    php_admin_flag engine off 
    <filesmatch "(.*)php">
        Order deny,allow
        Deny from all 
    </filesmatch>
</Directory>

說明:
php_admin_flag engine off 這個語句就是禁止解析php的控制語句,但只這樣配置還不夠,因為這樣配置後使用者依然可以訪問php檔案,
只不過不解析了,但可以下載,使用者下載php檔案也是不合適的,所以有必要再禁止一下。

十、禁止指定user_agent
user_agent叫做瀏覽器標識,目前主流的瀏覽器有IE、chrome、Firefox、360、iphone的Safari、Android手機上的、百度搜尋引擎、google搜尋引擎等很多,每一種瀏覽器都有對應的user_agent。為了避免一些無用的搜尋引擎或機器爬蟲之類引起的頻寬的無辜消耗。

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^www.kevin.com$ [OR]
    RewriteCond %{HTTP_HOST} ^www.abcd.com$
    RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]

    RewriteCond %{HTTP_USER_AGENT} ".*Firefox.*" [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} ".*Tomato Bot.*" [NC]
    RewriteRule .* - [F] 
</IfModule>

同樣是使用rewrite模組來實現限制指定user_agent。本例中:
RewriteRule .* - [F]    可以直接禁止訪問;
rewritecond用user_agent來匹配,NC表示不區分大小寫,OR表示或者,連線下一個條件。

假如我們要把百度的搜尋引擎限制掉,可以加一條這樣的規則:
RewriteCond %{HTTP_USER_AGENT} ^.*Baiduspider/2.0.* [NC]
RewriteRule .* - [F]

十一、限制某個目錄
可以allow和deny去現在網站根目錄下的某個子目錄,當然這個rewrite也可以實現。

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^.*/shibo/* [NC]
    RewriteRule .* - [F]
</IfModule>

這段配置,會把只要是包含 /shibo/ 字樣的請求都限制了。

十二、讓Apache伺服器的使用者都有自己的URL,有自己的網頁空間

配置檔案裡新增下面一行內容:
UserDir public_html    
  
配置檔案中有這行指令後,再在使用者主目錄下建立public_html目錄,裡面放入網頁就可以了。
訪問的URL,以kevin這個使用者為例:http://192.168.10.10/~kevin/

還要將配置檔案中一段註釋去掉:
#<Directory /home/*/public_html>
#    AllowOverride FileInfo AuthConfig Limit Indexes
#    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
#    <Limit GET POST OPTIONS PROPFIND>
#        Order allow,deny
#        Allow from all
#    </Limit>
#    <LimitExcept GET POST OPTIONS PROPFIND>
#        Order deny,allow
#        Deny from all
#    </LimitExcept>
#</Directory>
  
以配置訪問許可權。


另一種方式是在配置檔案中新增下面一行內容:
UserDir /www/user/*/htdocs

這種方法後的引數是完整的路徑名,把使用者的頁面檔案都放在了統一的目錄下(/www/usr/下),
後面的*號是使用者名稱命名的目錄。訪問方法和上面第一種方法一樣。

十三、Apache的.htaccess檔案配置說明
.htaccess檔案是Apache伺服器中的一個配置檔案,它負責相關目錄下的網頁配置。通過對.htaccess檔案進行設定,可以幫我們實現:網頁301重定向、自定義400/403/404/500錯誤頁面、改變副檔名、允許/阻止指定IP使用者訪問、禁止目錄列表、配置預設文件等功能,可以說是功能非常強大。

設定網站錯誤頁面
ErrorDocument 400 /error_pages/400.html
ErrorDocument 401 /error_pages/401.html
ErrorDocument 403 /error_pages/403.html
ErrorDocument 404 /error_pages/404.html
ErrorDocument 500 /error_pages/500.html
  
設定網頁301重定向
#從 old_dir 目錄重定向到 new_dir 目錄
Redirect /old_dir/ http://www.yourdomain.com/new_dir/index.html
#把通過二級目錄訪問的請求301重定向到二級域名
RedirectMatch 301 /dir/(.*) http://dir.yourdomain.com/$1
  
禁止指定IP段使用者的訪問
#禁止 IP 為 255.0.0.0 和 123.45.6.區段的 IP 訪問
order allow,deny
deny from 255.0.0.0
deny from 123.45.6.
allow from all
  
禁止指定來源網頁訪問
#禁止從 otherdomain.com 和 anotherdomain.com 的來源訪問
RewriteEngine on
# Options +FollowSymlinks
RewriteCond %{HTTP_REFERER} otherdomain\.com [NC,OR]
RewriteCond %{HTTP_REFERER} anotherdomain\.com
RewriteRule .* – [F]
  
圖片防盜鏈設定
#從本站以外的域名訪問圖片,一律顯示 feed.jpg
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?yourdomain.com/.*$ [NC]
RewriteRule \.(gif|jpg|png)$ http://www.yourdomain.com/feed.jpg [R,L]
  
設定資料夾首頁
#防止顯示資料夾列表,當訪問資料夾時,伺服器會查詢index.html,並將其做為首頁檔案,如不存在依次向後查詢
DirectoryIndex index.html index.cgi index.php
  
設定多媒體檔案為可下載而非播放
AddType application/octet-stream .mp3 .mp4
  
自定義HTTP報頭
Header set X-Pingback “http://www.yourdomain.com/xmlrpc.php”
Header set article-by “yourdomain.com”
  
設定檔案過期時間 Cache Control
# 啟用有效期控制
ExpiresActive On
# gif/png/jpg 有效期為1個月
ExpiresByType image/gif “access plus 1 month”
ExpiresByType image/png “access plus 1 month”
ExpiresByType image/jpg “access plus 1 month”
# js/css 有效期為1星期
ExpiresByType text/javascript “access plus 1 week”
ExpiresByType text/css “access plus 1 week”
  
WordPress建站程式偽靜態程式碼
# BEGIN WordPress          #這是一行註釋,表示 WordPress 的 htaccess 從這裡開始
#如果Apache載入了mod_rewrite.c模組,則執行以下程式碼
RewriteEngine On             #啟用 mod_rewrite 引擎
RewriteBase /                    #設定目錄重寫的基準URL為 /
RewriteRule ^index\.php$ – [L]              #如果請求路徑是 index.php,停止重寫操作(避免死迴圈)
RewriteCond %{REQUEST_FILENAME} !-f               #如果請求的不是一個檔案,繼續處理
RewriteCond %{REQUEST_FILENAME} !-d              #如果請求的不是一個目錄,繼續處理
RewriteRule . /index.php [L]                 #把所有的請求指向 /index.php
#結束 IfModule
# END WordPress #WordPress 的 htaccess 到這裡結束
  
Discuz x3/x3.1通用偽靜態程式碼
#如果Apache載入了mod_rewrite.c模組,則執行以下程式碼
RewriteEngine On
RewriteBase /discuz
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^topic-(.+)\.html$ portal.php?mod=topic&topic=$1&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^article-([0-9]+)-([0-9]+)\.html$ portal.php?mod=view&aid=$1&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^forum-(\w+)-([0-9]+)\.html$ forum.php?mod=forumdisplay&fid=$1&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ forum.php?mod=viewthread&tid=$1&extra=page\%3D$3&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^group-([0-9]+)-([0-9]+)\.html$ forum.php?mod=group&fid=$1&page=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^space-(username|uid)-(.+)\.html$ home.php?mod=space&$1=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^blog-([0-9]+)-([0-9]+)\.html$ home.php?mod=space&uid=$1&do=blog&id=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^archiver/(fid|tid)-([0-9]+)\.html$ archiver/index.php?action=$1&value=$2&%1
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ plugin.php?id=$1:$2&%1

#http強轉為https配置
RewriteEngine on         
RewriteBase /            
RewriteCond %{SERVER_PORT} !^443$   
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]   

----------------------------------------------其他注意點---------------------------------------------

AliasMatch指令:可以用正規表示式的方式將多個URL對應至同一個目錄。
例如配置如下:
AliasMatch ^/testph(p|ps) /usr/local/apache2/htdocs/php
 
以上配置表示:
可以用
http://www.kevin.com/testphp/phpinfo.php
和
http://www.kevin.com/testphps/phpinfo.php
來訪問同一個目錄/usr/local/apache2/htdocs/php中的內容
================================
重定向至其他URL:
修改配置檔案:
Redirect /xueer http://www.bo.com/yiner
 
以上指令表示訪問http:www.kevin.com/xueer時,實際訪問的是http://www.bo.com/yiner
   
Redirect指令有幾個引數:
temp:表示檔案當前不在原來所請求的位置上,可以將來還會在這個位置上,現在只是臨時的。這樣,客戶端會記住原始請求的URL。
permanent:表示被請求的檔案不在指定位置上,而是永久在新的位置上。這樣,客戶端會記住新的URL
gone:表示檔案不在此位置,而且以後也不在新的位置上。相當於404錯誤。但伺服器會承認所請求的檔案原來在此位置。所以不會被視為錯誤。
seeother:表示檔案不在所請求的位置,而且被不同位置的其它檔案取代了(前三個引數都是指同一個檔案,這個引數請是不同位置的不同檔案取代了原來位置的原來檔案)
   
預設情況下是使用temp引數
用RedirectMatch指令可以用正規表示式的方式將多個URL重定向至同一位置。
================================
Apache接受不區分大小寫的URL:
1) 安裝mod_speling模組
2) 在配置檔案中新增:
CheckSpelling On
================================
mod_rewrite模組用途:
可以重寫URL請求中的檔案,替換成指定的;
可以拒絕訪問未被引用的請求;
可以依據查詢字串來重寫;
可以將所有請求重定向是單一主機;
將伺服器的全部或部分請求重定向至SSL等相關工作
================================
Apache效能測試:
# ab -n 1000 -c 20 http://www.baidu.com/back.html     
其中:
-n  1000 表示請求的數目
-c  20 表示一次送出20 個請求
-h  可以檢視幫助
================================
Apache取得網站快照:
修改配置檔案:
<Location /server-status>
    SetHandler server-status
#    Order deny,allow
#    Deny from all
#    Allow from .example.com
</Location>
ExtendedStatus On
================================
將經常檢視的檔案存入快取記憶體區:
修改配置檔案:
MMapFile /usr/local/apache2/htdocs/index.html           
需要安裝mod_file_cache模組
================================
將目錄列表存入快取記憶體區
修改配置檔案:
IndexOptions +TrackModified

==============一個簡單的apache跳轉頁面配置的小示例=================

示例如下:
假設apache的域名(ServerName)為www.kevin.com
 
下面配置表示:
訪問http://www.kevin.com/shibo/admin/下匹配的path資源不存在時,頁面跳轉到 http://www.kevin.com/missing.html 的404錯誤頁面。
要是admin下匹配的path資源存在,則不會跳轉!
<IfModule proxy_module>
  ProxyPass /shibo/admin/*  http://www.kevin.com/missing.html
  ProxyPassMatch  /shibo/admin/*  !
</IfModule>
 
下面配置表示:
訪問http://www.kevin.com/shibo/admin/下匹配的所有資源時,頁面跳轉到 http://www.kevin.com/missing.html 的404錯誤頁面。
不管admin下匹配path資源存在還是不存在,都會跳轉!
<IfModule proxy_module>
  ProxyPass /shibo/admin/  http://www.kevin.com/missing.html
  ProxyPassMatch  /shibo/admin/  !
</IfModule>

以上的配置:
可以禁止在外網使用域名訪問時跳轉到missing.html的提示頁面。
但是在內網使用ip+port方式訪問,不會跳轉到missing.html提示頁面,會正常訪問。

十四、Apache Rewrite重寫規則總結

1)介紹
Apached的重寫功能,即是mod_rewrite模組功能,它是apache的一個模組。它的功能非常強大,可以操作URL中的所有部分。因此我們就可以改寫url,給使用者提供一個簡介大方的url,當使用者訪問時可以通過mod_rewrite模組功能轉換為真正的資源路徑。通過mod_rewrite能實現的功能還有很多,例如隱藏真實地址、實現URL跳轉、域名跳轉、防盜鏈、限制訪問資源型別等等。

2)工作流程
mod_rewrite模組在執行時會使用兩個Hook程式。
a)第一個是從URL到檔名轉換的Hook。當有訪問到達Apache伺服器的時,伺服器會確認相應主機(或虛擬主機),這時mod_rewrite模組就開始工作,它將會先處理伺服器全域性中mod_rewrite模組所提供的指令,然後根據使用者提供的指令進行改寫。
b)第二個是修正URL的Hook。在此階段mod_rewrite模組會處理非全域性的設定。例如,目錄中的.htaccess檔案中的設定。但是此時已經完成URL的翻譯(由URL轉換為檔名),因此是無法在次對目錄級別的URL進行改寫操作,但是moe_rewrite模組會將已翻譯的URL再次轉換為URL的狀態,繼續進行目錄級別的URL改寫。(mod_rewrite模組將會使用讀後請求階段的回叫函式重新開始一個請求的迴圈處理)

Rewirte模組規則集的處理
當mod_rewrite在這兩個API階段中開始執行時,它會讀取配置結構中配置好的 (或者是在服務啟動時建立的伺服器級的,或者是在遍歷目錄採集到的目錄級的)規則集,然後,啟動URL重寫引擎來處理(帶有一個或多個條件的)規則集。無論是伺服器級的還是目錄級的規則集,都是由同一個URL重寫引擎處理,只是最終結果處理不同而已。
規則集中規則的順序是很重要的,因為重寫引擎是按一種特殊的順序處理的:逐個遍歷每個規則(RewriteRule指令),如果出現一個匹配條件的規則,則可能回頭遍歷已有的規則條件(RewriteCond指令)。由於歷史的原因,條件規則是前置的,所以控制流程略顯冗長,細節見下圖-1。

可見,URL首先與每個規則的Pattern匹配,如果匹配失敗,mod_rewrite將立即終止此規則的處理,繼而處理下一個規則。如果匹配成功,mod_rewrite將尋找相應的規則條件,如果一個條件都沒有,則簡單地用Substitution構造的新值來替換URL,然後繼續處理其他規則;但是如果條件存在,則開始一個內部迴圈按其列出的順序逐個處理。對規則條件的處理有所不同:URL並不與模式進行匹配,而是首先通過擴充套件變數、反向引用、查詢對映表等步驟建立一個TestString字串,然後用它來與CondPattern匹配。如果匹配失敗,則整個條件集和對應的規則失敗;如果匹配成功,則執行下一個規則直到所有條件執行完畢。如果所有條件得以匹配,則以Substitution替換URL,並且繼續處理。(本部分引用譯者:金步國)

網路圖片:

3)URL重寫指令
只需要兩步就可以完成了。第一使用RewriteEngine開啟mod_rewrite模組功能;第二通過RewriteRule定義URL重寫規則。
3.1)URL重寫指令套路

RewriteEngine on                 #開啟mod_rewrite模組功能
RewriteBase 路徑                  #基準URL(使用alias設定別名則需使用這個)
RewriteCond TestString CondPattern [flags]          #重寫條件(可以多個)
RewriteRule Pattern Substitution [flags]                 #重寫規則

#最後兩行可以可以多個
#按順序一個一個執行RewriteRule([flags不終止情況下])
##以上是常用的指令,還有一些很少見的指令,需要的自己去查資料瞭解

3.2)RewriteRule Pattern Substitution [flags]
a)pattern是作用於當前URL的perl相容的正規表示式。當前URL是指該規則生效時刻的URL的值。它可能與被請求時的URL截然不同,因為之前可能被其他RewriteRule或者alias指令修改過。
b)Substitution是當URL與Pattern匹配成功後。用來代替的字串。
- 可以對pattern反向引用$N(N=0~9),表示正規表示式中第N個括號中的內容
- 對最後匹配的RewriteCond反向引用%N(N=0~9),表示最後匹配的RewriteCond第N對括號中的內容
- 伺服器變數%{VARNAME}
- 對映函式呼叫${mapname:key|default} (通過RewriteMap指令定義對映輔助完成)

c)[flags],標誌符,多個則用逗號隔開。

redirect|R [=code] (強制重定向 redirect)
以 http://thishost[:thisport]/(使新的URL成為一個URI) 為字首的Substitution可以強制性執行一個外部重定向。 如果code沒有指定,則產生一個HTTP響應程式碼302(臨時性移動)。如果需要使用在300-400範圍內的其他響應程式碼,只需在此指定這個數值即可, 另外,還可以使用下列符號名稱之一: temp (預設的), permanent, seeother. 用它可以把規範化的URL反饋給客戶端,如, 重寫“/~”為 “/u/”,或對/u/user加上斜槓,等等。

注意: 在使用這個標記時,必須確保該替換欄位是一個有效的URL! 否則,它會指向一個無效的位置! 並且要記住,此標記本身只是對URL加上 http://thishost[:thisport]/的字首,重寫操作仍然會繼續。通常,你會希望停止重寫操作而立即重定向,則還需要使用’L’標記.

forbidden|F (強制URL為被禁止的 forbidden)
強制當前URL為被禁止的,即,立即反饋一個HTTP響應程式碼403(被禁止的)。使用這個標記,可以連結若干RewriteConds以有條件地阻塞某些URL。

gone|G(強制URL為已廢棄的 gone)
強制當前URL為已廢棄的,即,立即反饋一個HTTP響應程式碼410(已廢棄的)。使用這個標記,可以標明頁面已經被廢棄而不存在了.

proxy|P (強制為代理 proxy)
此標記使替換成分被內部地強制為代理請求,並立即(即, 重寫規則處理立即中斷)把處理移交給代理模組。你必須確保此替換串是一個有效的(比如常見的以 http://hostname開頭的)能夠為Apache代理模組所處理的URI。使用這個標記,可以把某些遠端成分對映到本地伺服器名稱空間, 從而增強了ProxyPass指令的功能。

注意: 要使用這個功能,代理模組必須編譯在Apache伺服器中。 如果你不能確定,可以檢查“httpd -l”的輸出中是否有mod_proxy.c。 如果有,則mod_rewrite可以使用這個功能;如果沒有,則必須啟用mod_proxy並重新編譯“httpd”程式。

last|L (最後一個規則 last)
立即停止重寫操作,並不再應用其他重寫規則。 它對應於Perl中的last命令或C語言中的break命令。這個標記可以阻止當前已被重寫的URL為其後繼的規則所重寫。 舉例,使用它可以重寫根路徑的URL(’/’)為實際存在的URL, 比如, ‘/e/www/’.

next|N (重新執行 next round)
重新執行重寫操作(從第一個規則重新開始). 這時再次進行處理的URL已經不是原始的URL了,而是經最後一個重寫規則處理的URL。它對應於Perl中的next命令或C語言中的continue命令。 此標記可以重新開始重寫操作,即, 立即回到迴圈的頭部。
但是要小心,不要製造死迴圈!

chain|C (與下一個規則相連結 chained)
此標記使當前規則與下一個(其本身又可以與其後繼規則相連結的, 並可以如此反覆的)規則相連結。 它產生這樣一個效果: 如果一個規則被匹配,通常會繼續處理其後繼規則, 即,這個標記不起作用;如果規則不能被匹配,則其後繼的連結的規則會被忽略。比如,在執行一個外部重定向時, 對一個目錄級規則集,你可能需要刪除“.www” (此處不應該出現“.www”的)。

type|T=MIME-type(強制MIME型別 type)
強制目標檔案的MIME型別為MIME-type。 比如,它可以用於模擬mod_alias中的ScriptAlias指令,以內部地強制被對映目錄中的所有檔案的MIME型別為“application/x-httpd-cgi”。

nosubreq|NS (僅用於不對內部子請求進行處理 no internal sub-request)
在當前請求是一個內部子請求時,此標記強制重寫引擎跳過該重寫規則。比如,在mod_include試圖搜尋可能的目錄預設檔案(index.xxx)時, Apache會內部地產生子請求。對子請求,它不一定有用的,而且如果整個規則集都起作用,它甚至可能會引發錯誤。所以,可以用這個標記來排除某些規則。

根據你的需要遵循以下原則: 如果你使用了有CGI指令碼的URL字首,以強制它們由CGI指令碼處理,而對子請求處理的出錯率(或者開銷)很高,在這種情況下,可以使用這個標記。

nocase|NC (忽略大小寫 no case)
它使Pattern忽略大小寫,即, 在Pattern與當前URL匹配時,’A-Z’ 和’a-z’沒有區別。

qsappend|QSA (追加請求串 query string append)
此標記強制重寫引擎在已有的替換串中追加一個請求串,而不是簡單的替換。如果需要通過重寫規則在請求串中增加資訊,就可以使用這個標記。

noescape|NE (在輸出中不對URI作轉義 no URI escaping)
此標記阻止mod_rewrite對重寫結果應用常規的URI轉義規則。 一般情況下,特殊字元(如’%’, ‘$’, ‘;’等)會被轉義為等值的十六進位制編碼。 此標記可以阻止這樣的轉義,以允許百分號等符號出現在輸出中,如:
RewriteRule /foo/(.*) /bar?arg=P1=$1 [R,NE] 可以使’/foo/zed’轉向到一個安全的請求’/bar?arg=P1=zed’.

passthrough|PT (移交給下一個處理器 pass through)
此標記強制重寫引擎將內部結構request_rec中的uri欄位設定為 filename欄位的值,它只是一個小修改,使之能對來自其他URI到檔名翻譯器的 Alias,ScriptAlias, Redirect 等指令的輸出進行後續處理。舉一個能說明其含義的例子:如果要通過mod_rewrite的重寫引擎重寫/abc為/def,然後通過mod_alias使/def轉變為/ghi,可以這樣:
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi

如果省略了PT標記,雖然mod_rewrite運作正常, 即, 作為一個使用API的URI到檔名翻譯器,它可以重寫uri=/abc/…為filename=/def/…,但是,後續的mod_alias在試圖作URI到檔名的翻譯時,則會失效。

注意: 如果需要混合使用不同的包含URI到檔名翻譯器的模組時, 就必須使用這個標記。。混合使用mod_alias和mod_rewrite就是個典型的例子。

For Apache hackers
如果當前Apache API除了URI到檔名hook之外,還有一個檔名到檔名的hook, 就不需要這個標記了! 但是,如果沒有這樣一個hook,則此標記是唯一的解決方案。 Apache Group討論過這個問題,並在Apache 2.0 版本中會增加這樣一個hook。

skip|S=num (跳過後繼的規則 skip)
此標記強制重寫引擎跳過當前匹配規則後繼的num個規則。 它可以實現一個偽if-then-else的構造: 最後一個規則是then從句,而被跳過的skip=N個規則是else從句. (它和’chain|C’標記是不同的!)

env|E=VAR:VAL (設定環境變數 environment variable)
此標記使環境變數VAR的值為VAL, VAL可以包含可擴充套件的反向引用的正規表示式$N和%N。 此標記可以多次使用以設定多個變數。這些變數可以在其後許多情況下被間接引用,但通常是在XSSI (via ) or CGI (如 $ENV{’VAR’})中, 也可以在後繼的RewriteCond指令的pattern中通過%{ENV:VAR}作引用。使用它可以從URL中剝離並記住一些資訊。

cookie|CO=NAME:VAL:domain[:lifetime[:path]] (設定cookie)
它在客戶端瀏覽器上設定一個cookie。 cookie的名稱是NAME,其值是VAL。 domain欄位是該cookie的域,比如’.apache.org’, 可選的lifetime是cookie生命期的分鐘數,可選的path是cookie的路徑。

3.3)RewriteCond TestString CondPattern [flags]
Rewritecond指令定義一條規則條件。在一條rewriterule指令前面可能會有一條或者多條rewritecond指令,只有當自身模板匹配成功且這些條件也滿足時(即RewriteRule中的pattern匹配成功),規則條件才被應用於當前URL處理。

3.3.1)TestString是一個純文字的字串
可以對pattern反向引用$N(N=0~9),緊跟在RewriteCond後面的RewriteRule正規表示式中第N個括號中的內容
反向引用%N(N=0~9),表示RewriteCond中CondPattern中第N對括號中的內容
伺服器變數%{VARNAME}

3.3.2)CondPattern是條件pattern,一個應用於當前例項TestString的正規表示式。即TestString與條件pattern條件進行匹配。如果匹配則RewriteCond的值為Rrue,反之為False

可以使用以下特殊變數(可使用'!'實現反轉)
'>CondPattern’ (大於) 將condPattern當作一個普通字串,將它和TestString進行比較,當TestString 的字元大於CondPattern為真。
‘=CondPattern’ (等於) 將condPattern當作一個普通字串,將它和TestString進行比較,當TestString 與CondPattern完全相同時為真.如果CondPattern只是 “” (兩個引號緊挨在一起) 此時需TestString 為空字串方為真。
‘-d’ (是否為目錄) 將testString當作一個目錄名,檢查它是否存在以及是否是一個目錄。
‘-f’ (是否是regular file) 將testString當作一個檔名,檢查它是否存在以及是否是一個regular檔案。
‘-s’ (是否為長度不為0的regular檔案) 將testString當作一個檔名,檢查它是否存在以及是否是一個長度大於0的regular檔案。
‘-l’ (是否為symbolic link) 將testString當作一個檔名,檢查它是否存在以及是否是一個 symbolic link。
‘-F’ (通過subrequest來檢查某檔案是否可訪問) 檢查TestString是否是一個合法的檔案,而且通過伺服器範圍內的當前設定的訪問控制進行訪問。這個檢查是通過一個內部subrequest完成的, 因此需要小心使用這個功能以降低伺服器的效能。
‘-U’ (通過subrequest來檢查某個URL是否存在) 檢查TestString是否是一個合法的URL,而且通過伺服器範圍內的當前設定的訪問控制進行訪問。這個檢查是通過一個內部subrequest完成的, 因此需要小心使用這個功能以降低伺服器的效能。

3.3.3)[flags]是第三個引數,多個標誌之間用逗號隔開)
’nocase|NC’ (不區分大小寫) 在擴充套件後的TestString和CondPattern中,比較時不區分文字的大小寫。注意,這個標誌對檔案系統和subrequest檢查沒有影響.
’ornext|OR’ (建立與下一個條件的或的關係) 預設的情況下,二個條件之間是AND的關係,用這個標誌將關係改為OR。

4)Rewrite時伺服器變數(僅列出少數)
HTTP headers:HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, HTTP_HOST, HTTP_ACCEPT
connection & request:REMOTE_ADDR, QUERY_STRING
server internals::DOCUMENT_ROOT, SERVER_PORT, SERVER_PROTOCOL
system stuff: TIME_YEAR, TIME_MON, TIME_DAY

5)簡單正規表示式規則
. 匹配任何單字元
[chars]   匹配字串:chars
[^chars]   不匹配字串:chars
text1|text2   可選擇的字串:text1或text2
?   匹配0到1個字元
*   匹配0到多個字元
匹配1到多個字元
^   字串開始標誌
$   字串結束標誌
\n   轉義符標誌

注意:一代Apache要求URL有斜槓而二代Apache卻不允許,因此使用 ^/?

6)Rewirte主要的功能就是實現URL的跳轉,它的正規表示式是基於Perl語言。
可基於伺服器級的(httpd.conf)和目錄級的 (.htaccess)兩種方式。如果要想用到rewrite模組,必須先安裝或載入rewrite模組,方法有兩種:
一種是編譯apache的時候就直接 安裝rewrite模組。
另一種是編譯apache時以DSO模式安裝apache,然後再利用原始碼和apxs來安裝rewrite模組。

基於伺服器級的(httpd.conf)有兩種方法,一種是在httpd.conf的全域性下直接利用RewriteEngine on來開啟rewrite功能;另一種是在區域性裡利用RewriteEngine on來開啟rewrite功能,下面將會舉例說明,需要注意的是,必須在每個virtualhost裡用RewriteEngine on來開啟rewrite功能。否則virtualhost裡沒有RewriteEngine on它裡面的規則也不會生效。

基於目錄級的(.htaccess),要注意一點那就是必須開啟此目錄的FollowSymLinks屬性且在.htaccess裡要宣告 RewriteEngine on。

rewrite跳轉舉列說明

示例一:
下面是在一個虛擬主機裡定義的規則。功能是把client請求的主機字首不是www.kevin.cn和192.168.10.20都跳轉到主機字首為http://www.bobo.cn, 避免相同
內容的網頁有多個指向的域名,如http://kevin.cn。

配置如下:
NameVirtualHost 192.168.10.20:80
ServerAdmin slj@bobo.cn
DocumentRoot “/web”
ServerName kevin.cn

RewriteEngine on  #開啟rewirte功能
RewriteCond %{HTTP_HOST} !^www.kevin.cn [NC]  #宣告Client請求的主機中字首不是www.kevin.cn, 其中 [NC] 的意思是忽略大小寫
RewriteCond %{HTTP_HOST} !^192.168.10.20 [NC]    #宣告Client請求的主機中字首不是192.168.10.20,其中 [NC] 的意思是忽略大小寫
RewriteCond %{HTTP_HOST} !^$  #宣告Client請求的主機中字首不為空
RewriteRule ^(.*) http://www.bobo.cn/ [L]    

#最後一行含義是如果Client請求的主機中的字首符合上述條件,則直接進行跳轉到http://www.bobo.cn/,[L]意味著立即停止重寫操作,並不再應用其他重寫規則。
這裡的.*是指匹配所有URL中不包含換行字元,()括號的功能是把所有的字元做一個標記,以便於後面的應用.就是引用前面裡的 (.*)字元。

=============================================
示例二:將輸入 hui.com 的域名時跳轉到http://www.kevin.cn

配置如下:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^hui.com [NC]
RewriteRule ^(.*) http://www.kevin.cn/ [L]

=============================================
示例三:
近期更換了域名,新域名為www.grace.com, 更加簡短好記。這時需要將原來的域名ss.bobo.cn, 以及論壇所在地址ss.bobo.cn/bbs/定向到新的域名,
以便使用者可以找到,並且使原來的論壇URL繼續有效而不出現404未找到,比如原來的http://ss.bobo.cn/bbs/tread-60.html, 讓它在新的域名下繼續
有效,點選後轉發到http://bbs.grace.com/tread-60.html,而其他網頁,如原先的http: //ss.bobo.cn/purchase不會到二級域名bbs.grace.com/purchase上,
而是到 www.grace.com/purchase按照這樣的要求重定向規則應該這樣寫:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/bbs/
RewriteRule ^bbs/(.*) http://bbs.grace.com/$1 [R=permanent,L]
RewriteCond %{REQUEST_URI} !^/bbs/
RewriteRule ^(.*) http://www.grace.com/$1 [R=permanent,L]

=============================================
示例四:同時達到下面兩個要求:
用http://www.kevin.cn/xxx.php 來訪問http://www.kevin.cn/xxx/
用http://xiaoye.kevin.cn 來訪問 http://www.kevin.cn/user.php?username=xiaoye的功能

配置如下:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.kevin.cn
RewriteCond %{REQUEST_URI} !^user.php$
RewriteCond %{REQUEST_URI} .php$
RewriteRule (.*).php$ http://www.kevin.cn/$1/ [R]
RewriteCond %{HTTP_HOST} !^www.kevin.cn
RewriteRule ^(.+) %{HTTP_HOST} [C]
RewriteRule ^([^.]+).kevin.cn http://www.kevin.cn/user.php?username=$1

=============================================
示例五:實現下面要求:
/type.php?typeid=* –> /type*.html
/type.php?typeid=*&page=* –> /type*page*.html

配置如下:
RewriteRule ^/type([0-9]+).html$ /type.php?typeid=$1 [PT]
RewriteRule ^/type([0-9]+)page([0-9]+).html$ /type.php?typeid=$1&page=$2 [PT]

=============================================
示例六:使用Apache的URL Rewrite配置多使用者虛擬伺服器

要實現這個功能,首先要在DNS伺服器上開啟域名的泛域名解析(自己做或者找域名服務商做)。
比如,把 *.bobo.us和 *.bobo.cn全部解析到IP地址為70.40.213.183上。Apache中關於*.bobo.us的虛擬主機的設定如下:

ServerAdmin webmaster@bobo.us
DocumentRoot /home/www/www.bobo.us
ServerName dns.bobo.us
ServerAlias dns.bobo.us bobo.us *.bobo.us
CustomLog /var/log/httpd/osa/access_log.log” common
ErrorLog /var/log/httpd/osa/error_log.log”
AllowOverride None
Order deny,allow

#AddDefaultCharset GB2312
RewriteEngine on
RewriteCond %{HTTP_HOST} ^[^.]+.bobo.(cn|us)$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^([^.]+).bobo.(cn|us)(.*)$ /home/www/www.bobo.us/sylvan$3?un=$1&%{QUERY_STRING} [L]

配置說明:
在上面這段設定中,把*.bobo.cn和*.bobo.us 的Document Root都設定到了 /home/www/www.bobo.us
繼續看下去,這裡配置了URL Rewrite規則。
倒數第四行表示:開啟URL Rewrite功能
倒數第三行表示:匹配條件,如果使用者輸入的URL中主機名是類似 xxxx.bobo.us 或者 xxxx.bobo.cn 就執行下面一句
倒數第二行表示:把使用者輸入完整的地址(GET方式的引數除外)作為引數傳給下一個規則,[C]是Chain串聯下一個規則的意思
倒數第一行:最關鍵的是這一句,使用證則表示式解析使用者輸入的URL地址,把主機名中的使用者名稱資訊作為名為un的引數傳給/home/www/dev.bobo.us 目錄下的指令碼,
並在後面跟上使用者輸入的GET方式的傳入引數。並指明這是最後一條規則([L]規則)。注意,在這一句中指明的重寫後的地址用的是伺服器上 的絕對路徑,這是內部跳轉。
如果使用http://xxxx這樣的URL格式,則被稱為外部跳轉。使用外部跳轉的話,瀏覽著的瀏覽器中的URL地址會改變成新的地址,而使用內部跳轉則瀏覽器中的地址不發生
改變,看上去更像實際的二級域名虛擬伺服器。

=============================================
示例七:Rewrite 防盜鏈正則
不允許www.im286.com和www.chinaz.com 這兩個網站盜鏈 , 其它的網站都可以盜鏈。

配置如下:
RewriteEngine On
RewriteCond %{HTTP_REFERER} chinaz.com [NC]
RewriteCond %{HTTP_REFERER} im286.com [NC]
RewriteRule .*\.(jpg|jpeg|gif|png|rar|zip|txt|ace|torrent|gz|swf)$ http://www.xxx.com/fuck.png [R,NC,L]

=============================================
示例七:關於判斷 USER AGENT 。配置如下:

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^MSIE [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^Opera [NC]
RewriteRule ^.* – [F,L] 

#這裡”-”表示沒有替換,瀏覽器為IE和Opera的訪客將被禁止訪問。 

=============================================
示例八:自動新增.php副檔名及自動換.html到.php副檔名。

配置如下:
RewriteEngine On
RewriteBase /test
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ([^/]+)$ /test/$1.php
#for hui: /test/admin => /test/admin.php

RewriteRule ([^/]+)\.html$ /test/$1.php [L]
#for hui: /test/admin.html => /test/admin.php

=============================================
示例九:限制目錄只能顯示圖片

配置如下:
< IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !^.*\.(gif|jpg|jpeg|png|swf)$
RewriteRule .*$ – [F,L]
< /IfModule> 

7)apache重寫規則的示例解析                                                                                                                                                                

在.htaccess裡進行規制重寫:
RewriteEngine ON
RewriteRule  ^user/(w+)/?$user.php?id=$1
 
配置說明:
^:輸入的開頭  以user/開頭請求的地址
(w+):提取所有的字母,傳給$1
/?:可選斜槓
$:結束符
替換為:user.php?id=*
 
注意:
有些apache不相容簡寫模式 w+ => [a-zA-Z_-]
 
===============================
禁止IE和Opera瀏覽器訪問
 
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^MSIE [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^Opera [NC]
RewriteRule ^.* - [F,L]       #'-'表示不替換URL
 
===============================
不合法路徑返回首頁
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
 
==============================
防盜鏈
 
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(.+.)?mysite.com/ [NC]          #判斷請求的是否是自己的域名
RewriteCond %{HTTP_REFERER} !^$                        #{HTTP_REFERER}不為空
RewriteRule .*.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]         #返回警告圖片
 
==============================
改變訪問URL目錄名),即隱藏真實的目錄名字
 
RewriteEngine On
RewriteRule ^/?old_dir/([a-z\.]+)$  new_dir/$1 [R=301,L]
#new_dir為真正目錄
 
==============================
建立無檔案字尾連結
 
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.php -f                #判斷該字尾檔案是否存在
RewriteRule ^/?([a-zA-Z0-9]+)$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.html -f               #判斷該字尾檔案是否存在
RewriteRule ^/?([a-zA-Z0-9]+)$ $1.html [L]
 
==============================
限制只能顯示圖片
 
RewriteEngine on
RewriteCond %{REQUEST_FILENAME}  !^.*\.(gif|jpg|jpeg|png|swf)$
RewriteRule .*$ - [F,L]
 
==============================
檔案不存在重定向404
 
RewriteEngine on
RewriteCond  %{REQUEST_FILENAME}  !f
RewriteCond  %{REQUEST_FILENAME}  !d
RewriteRule .? /404.php [L]

====================================其他配置示例====================================
1)去掉域名中的www標記
RewriteCond %{HTTP_HOST} !^jkevin\.net$ [NC]
RewriteRule .? http://jkevin.net%{REQUEST_URI} [R=301,L]
  
2)去掉www標記,但是儲存子域名
RewriteCond %{HTTP_HOST} ^www\.(([a-z0-9_]+\.)?jkevin\.net)$ [NC]
RewriteRule .? http://%1%{REQUEST_URI} [R=301,L]
  
這裡,當匹配到1%變數以後,子域名才會在%2(內部原子)中抓取到,而我們需要的正是這個%1變數。
  
3)給子域名加www標記
RewriteCond %{HTTP_HOST} ^([a-z.]+)?jkevin\.net$ [NC]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .? http://www.%1jkevin.net%{REQUEST_URI} [R=301,L]
  
這個規則抓取二級域名的%1變數,如果不是以www開始,那麼就加www,以前的域名以及{REQUEST_URI}會跟在其後。
  
4)防止圖片盜鏈
一些站長不擇手段的將你的圖片盜鏈在他們網站上,耗費你的頻寬。你可以加一下程式碼阻止這種行為。
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?jkevin\.net/ [NC]
RewriteRule \.(gif|jpg|png)$ – [F]
  
如果{HTTP_REFERER}值不為空,或者不是來自你自己的域名,這個規則用[F]FLAG阻止以gif|jpg|png 結尾的URL
如果對這種盜鏈你是堅決鄙視的,你還可以改變圖片,讓訪問盜鏈網站的使用者知道該網站正在盜用你的圖片。
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?jkevin\.net/.*$ [NC]
RewriteRule \.(gif|jpg|png)$ 你的圖片地址 [R=301,L]
  
除了阻止圖片盜鏈連結,以上規則將其盜鏈的圖片全部替換成了你設定的圖片。
你還可以阻止特定域名盜鏈你的圖片:
RewriteCond %{HTTP_REFERER} !^http://(www\.)?leech_site\.net/ [NC]
RewriteRule \.(gif|jpg|png)$ – [F,L]
  
這個規則將阻止域名黑名單上所有的圖片連結請求。
當然以上這些規則都是以{HTTP_REFERER}獲取域名為基礎的,如果你想改用成IP地址,用{REMOTE_ADDR}就可以了。
  
5)如果檔案不存在重定向到404頁面
如果你的主機沒有提供404頁面重定向服務,那麼我們自己建立。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? /404.php [L]
  
這裡-f匹配的是存在的檔名,-d匹配的存在的路徑名。
這段程式碼在進行404重定向之前,會判斷你的檔名以及路徑名是否存在。
你還可以在404頁面上加一個?url=$1引數:
RewriteRule ^/?(.*)$ /404.php?url=$1 [L]
  
這樣,你的404頁面就可以做一些其他的事情,例如發一個郵件提醒,加一個搜尋等等。
  
6)重新命名目錄
如果你想在網站上重新命名目錄,試試這個:
RewriteRule ^/?old_directory/([a-z/.]+)$ new_directory/$1 [R=301,L]
  
在規則裡我新增了一個“.”(注意不是代表得所有字元,前面有轉義符)來匹配檔案的字尾名。
  
7)將.html字尾名轉換成.php
前提是.html檔案能繼續訪問的情況下,更新你的網站連結。
RewriteRule ^/?([a-z/]+)\.html$ $1.php [L]
  
這不是一個網頁重定向,所以訪問者是不可見的。讓他作為一個永久重定向(可見的),將FLAG修改[R=301,L]。
  
8)建立無檔案字尾名連結
如果你想使你的PHP網站的連結更加簡潔易記-或者隱藏檔案的字尾名,試試這個:
RewriteRule ^/?([a-z]+)$ $1.php [L]
  
如果網站混有PHP以及HTML檔案,你可以用RewriteCond先判斷該字尾的檔案是否存在,然後進行替換:
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^/?([a-zA-Z0-9]+)$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^/?([a-zA-Z0-9]+)$ $1.html [L]
  
如果檔案是以.php為字尾,這條規則將被執行。
  
9)檢查查詢變數裡的特定引數
如果在URL裡面有一個特殊的引數,你可用RewriteCond鑑別其是否存在:
複製程式碼 程式碼如下:
RewriteCond %{QUERY_STRING} !uniquekey=
RewriteRule ^/?script_that_requires_uniquekey\.php$ other_script.php [QSA,L]
  
以上規則將檢查{QUERY_STRING}裡面的uniquekey引數是否存在,如果{REQUEST_URI}值為script_that_requires_uniquekey,將會定向到新的URL。
  
10)刪除查詢變數
Apache的mod_rewrite模組會自動辨識查詢變數,除非你做了以下改動:
a).分配一個新的查詢引數(你可以用[QSA,L]FLAG儲存最初的查詢變數)
b).在檔名後面加一個“?”(比如index.php?)。符號“?”不會在瀏覽器的位址列裡顯示。
  
11)用新的格式展示當前URI
如 果這就是我們當前正在執行的URLs:/index.php?id=nnnn。我們非常希望將其更改成/nnnn並且讓搜尋引擎以新格式展現。首先,我們 為了讓搜尋引擎更新成新的,得將舊的URLs重定向到新的格式,但是,我們還得保證以前的index.php照樣能夠執行。是不是被我搞迷糊了?
實 現以上功能,訣竅就在於在查詢變數中加了一個訪問者看不到的標記符“marker”。我們只將查詢變數中沒有出現“marker”標記的連結進行重定向, 然後將原有的連結替換成新的格式,並且通過[QSA]FLAG在已有的引數加一個“marker”標記。
  
以下為實現的方式:
RewriteCond %{QUERY_STRING} !marker
RewriteCond %{QUERY_STRING} id=([-a-zA-Z0-9_+]+)
RewriteRule ^/?index\.php$ %1? [R=301,L]
RewriteRule ^/?([-a-zA-Z0-9_+]+)$ index.php?marker &id=$1 [L]
  
這 裡,原先的URL:http://www.jkevin.net/index.php?id=nnnn,不包含marker,所以被第一個規則永久重定向到 http://www.jkevin.net/nnnn,
第二個規則將http://www.jkevin.net/nnnn反定向到http: //www.jkevin.net/index.php?marker&id=nnnn,並且加了marker以及id=nnnn兩個變數,
最後 mod_rewrite就開始進行處理過程。
第二次匹配,marker被匹配,所以忽略第一條規則,這裡有一個“.”字元會出現在http://www.jkevin.net/index.php?marker&id=nnnn中,所以第二條規則也會被忽略,這樣我們就完成了。
  
注意,這個解決方案要求Apache的一些擴充套件功能,所以如果你的網站放於在共享主機中會遇到很多障礙。
  
12)保證安全服務啟用
Apache可以用兩種方法辨別你是否開啟了安全服務,分別引用{HTTPS}和{SERVER_PORT}變數:
RewriteCond %{REQUEST_URI} ^secure_page\.php$
RewriteCond %{HTTPS} !on
RewriteRule ^/?(secure_page\.php)$ https://www.jkevin.net/$1 [R=301,L]
  
以上規則測試{REQUEST_URI}值是否等於我們的安全頁程式碼,並且{HTTPS}不等於on。
如果這兩個條件同時滿足,請求將被重定向到安全服務URI.另外你可用{SERVER_PORT}做同樣的測試,443是常用的安全服務埠
RewriteCond %{REQUEST_URI} ^secure_page\.php$
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/?(secure_page\.php)$ https://www.jkevin.net/$1 [R=301,L]
  
13)在特定的頁面上強制執行安全服務
遇到同一個伺服器根目錄下分別有一個安全服務域名和一個非安全服務域名,所以你就需要用RewriteCond 判斷安全服務埠是否佔用,並且只將以下列表的頁面要求為安全服務:
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/?(page1|page2|page3|page4|page5)$ https://www.jkevin.net/%1[R=301,L]
  
以下是怎樣將沒有設定成安全服務的頁面返回到80埠:
RewriteCond %{ SERVER_PORT } ^443$
RewriteRule !^/?(page6|page7|page8|page9)$http://www.jkevin.net%{REQUEST_URI} [R=301,L]
其實Rewrite裡運用最多的還應該是正規表示式,如果瞭解點兒正則的話,寫起這個規則還是比較簡單的。
  
14) ProxyPass規則示例
  
訪問http://www.kevin.com/shibo/admin/下匹配的所有資源時,頁面跳轉到 http://www.kevin.com/missing.html 的404錯誤頁面。
<IfModule proxy_module>
  ProxyPass /shibo/admin/  http://www.kevin.com/missing.html
  ProxyPassMatch  /shibo/admin/  !
</IfModule>

===================其他補充=========================
Apache的URL地址重寫的方法:
--------------第一種方法--------------
Apache環境中如果要將URL地址重寫,正規表示式是最基本的要求,但對於一般的URL地址來說,基本的匹配就能實現我們大部分要求,因此除非是非常特殊的URL地址,
但這不是我要討論的範圍,簡單幾招學會Apache中URL地址重寫,通過例項展示,輕鬆學會URL地址重寫:
 
URL例項
重寫URL:http://www.baidu.com/?p=152
原始URL:http://www.baidu.com/p152.html
 
重寫規則:
^p([0-9]+)\.html      /?p=$1     [L]
 
正則基礎知識:
^ 匹配行的開始,匹配URL地址的開頭部分,對於RewriteRule而言,域名(http://www.biuuu.com)不是URL地址的一部分,如上:?p=152
() 分隔一個被捕獲的表示式,如上:([0-9]+)
[] 定義字元類,如上:[0-9] 表示從0-9的數字
+ 說明前面的字元可以被重複匹配1次或數次,如上:[0-9]+,表示任何數字組合
\ 字元轉義,如上:轉義.
 
其它:
[L] 表示last,停止匹配其它
 
方法如下:
1)開啟httpd.conf檔案,找到
#LoadModule rewrite_module modules/mod_rewrite.so 註釋前面#
2)開啟httpd-vhosts.conf檔案,在VirtualHost新增重寫規則,
RewriteEngine On
RewriteRule ^p([0-9]+)\.html      /?p=$1     [L]
 
基本上就上面這兩個步驟,其實總的來說,Apache中URL地址重寫還是比較簡單的,比看文件學習要快的多,不過要想深入瞭解還是有必要看看相關文件的,其它規則可以
自定義。記住一點:任何匹配其實就是一個正規表示式的替換過程。
 
建立友好的搜尋引擎URL地址對於PHP程式設計師來說非常重要,因此簡單學會Apache中URL地址重寫將是一項最基本的要求。
 
--------------第二種方法--------------
1)首先檢查是否已安裝rewrite模組:
cat httpd.conf | grep rewrite
LoadModule rewrite_module modules/mod_rewrite.so
 
2)生成偽靜態html連線:
生成偽靜態html
在<VirtualHost>段最後加入
RewriteEngine on
RewriteRule /goods([0-9]+).html /goods.php?id=$1 [PT] 
 
更標準的寫法為:
RewriteRule ^(.*)/goods([0-9]+).html$ $1/goods.php?id=$2 [PT]
 
更簡潔的寫法:
/goods(\d+)\.html /goods\.php\?id=$1
 
第一個(0-9]+)對應引數$1,以此類推第二個對應$2
 
舉例:
RewriteRule /forum-([0-9]+)-([0-9]+)\.html /forumdisplay.php?fid=$1&page=$2 [PT]
 
測試http://www.xxx.com/goods1.html 是否與/goods.php?id=1的內容相同。
最後將所有連結換成設定後的偽靜態html地址方式。
[PT]:url全域性轉換,即轉換過的goods31.html對應goods.php?id=31 (預設就是這個不加引數)
[R]:    url重定向  即使用goods31.html訪問時跳轉到goods.php?id=31
 
3)防盜鏈:
RewriteCrond %{HTTP_HOST} !upkiller.com [R=301,L]
RewriteRule ^(.*)$ http://www.upkiller.com/warning.html [R=301,L]
 
把不是來自upkiller.com的請求重定向到http://www.upkiller.com
 
更好的做法:
RewriteCond %{HTTP_REFERER} !^http://(www\.)?upkiller\.com/.*$ [NC]
RewriteRule \.(mp3|rar|jpe|gif)$ http://www.upkiller.com/warning.jpg [R=301,L]
 
4)防百度爬蟲:
RewriteCond %{HTTP_USER_AGENT} ^Baiduspider [OR]
RewriteRule ^(.*)$ http://www.google.com [R=301,L]
 
把來自百度的爬蟲轉到goole

=====================Apache的ProxyPass使用小結=====================
該指令可以將遠端伺服器對映到本地伺服器的URL空間;本地的伺服器並不是扮演傳統意義上的代理伺服器的角色,而是表現為遠端伺服器的一個映象。此本地伺服器常被成為反向代理(reversed proxy)或者是閘道器(gateway)。路徑是指本地虛擬路徑的名字;url指遠端伺服器的一個部分URL,不能包含查詢字串。

描述:將遠端伺服器對映到本地伺服器的URL空間
語法:ProxyPass [路徑] !|url [鍵=值 鍵=值 ...]] [nocanon]
上下文: server config, virtual host, directory
狀態:擴充套件
模組:mod_proxy

apache中的mod_proxy模組主要作用就是進行url的轉發,即具有代理的功能。應用此功能,可以很方便的實現同tomcat等應用伺服器的整合,甚者可以很方便的實現web叢集的功能。httpd.conf配置:

#保證以下模組載入  
LoadModule proxy_module modules/mod_proxy.so  
LoadModule proxy_http_module modules/mod_proxy_http.so  
#配置ProxyPass  
ProxyPass /new/ http://kevincom/  
ProxyPass /new2/ http://192.168.0.169:8080/  

需要注意:
順序很重要:排除的指令必須在一般的ProxyPass指令之前。上面的配置已經可以實現大部分功能了,要控制細節!

例子:
使用apache作為域名www.kevin.com代理伺服器,讓其暴露在公網上,即DNS解析到本機器上,真正提供web伺服器的是另一臺位於同一內網的機器上,假設起IP是172.16.50.40,那麼只需要如下配置就可以了。

ProxyPass / http://172.16.50.40/ 
ProxyPassReverse / http://172.16.50.40/

-   ProxyPass 很好理解,就是把所有來自客戶端對http://www.kevin.com的請求轉發給http://172.16.50.40上進行處理;
-   ProxyPassReverse的配置總是和ProxyPass 一致,但用途很讓人費解。似乎去掉它很能很好的工作,事實真的是這樣麼,其實不然,如果響應中有302重定向,ProxyPassReverse就派上用場。舉例說明,假設使用者訪問http://www.kevin.com/exam.php,通過轉發交給http://172.16.50.40 /exam.php處理,假定exam.php處理的結果是實現redirect到login.php(使用相對路徑,即省略了域名資訊),如果沒有配置反向代理,客戶端收到的請求響應是重定向操作,並且重定向目的url為http://172.16.50.40/login.php ,而這個地址只是代理伺服器能訪問到的,可想而知,客戶端肯定是打不開的,反之如果配置了反向代理,則會在轉交HTTP重定向應答到客戶端之前調整它為 http://www.kevin.com/login.php,即是在原請求之後追加上了redirect的路徑。當客戶端再次請求http: //www.kevin.com/login.php,代理伺服器再次工作把其轉發到http://172.16.50.40/login.php。
-   客戶端到伺服器稱之為正向代理,那伺服器到客戶端就叫反向代理。

ProxyPass與ProxyPassReverse及ProxyPassMatch這幾個都是Apache的代理指令
1)ProxyPass
語法:ProxyPass [path] !|url
它主要是用作URL字首匹配,不能有正規表示式,它裡面配置的Path實際上是一個虛擬的路徑,在反向代理到後端的url後,path是不會帶過去的。

示例一
ProxyPass / images/ !

這個示例表示,/images/的請求不被轉發。

=======================================
示例二:
ProxyPass /mirror/foo/ http://backend.kevin.com/

假設當前的服務地址是http://kevin.com/,如果做上面的配置,那麼訪問http://kevin.com/mirror/foo/bar將被轉成http://backend.kevin.com/bar
注:配置的時候,不需要被轉發的請求,要配置在需要被轉發的請求前面。

2)ProxyPassMatch
語法:ProxyPassMatch [regex] !|url
這個實際上是url正則匹配,而不是簡單的字首匹配,匹配上的regex部分是會帶到後端的url的,這個是與ProxyPass不同的。

示例一
ProxyPassMatch ^/images !

這個示例表示對/images的請求,都不會被轉發。

=======================================
示例二:
ProxyPassMatch ^(/.*.gif)  http://backend.kevin.com

這個示例表示對所有gif圖片的請求,都被會轉到後端,如此時請求,訪問http://kevin.com/foo/bar.gif 那內部將會轉換為 http://backend.kevin.com/foo/bar.gif。

3)ProxyPassReverse
語法:ProxyPassReverse [路徑] url)
它一般和ProxyPass指令配合使用,此指令使Apache調整HTTP重定向應答中Location, Content-Location, URI頭裡的URL,這樣可以避免在Apache作為反向代理使用時。
後端伺服器的HTTP重定向造成的繞過反向代理的問題。比如:

80埠的Proxypass跳轉
<IfModule proxy_module>
     ProxyPass  /companyNews  http://192.168.10.149:8080/companyNews
     ProxyPassReverse  /companyNews  http://192.168.10.149:8080/companyNews
     ProxyPass  /companyNews/*  http://192.168.10.149:8080/companyNews/*
     ProxyPassReverse  /companyNews/*  http://192.168.10.149:8080/companyNews/*
</IfModule>
  
<IfModule proxy_module>
     ProxyPass  /mlslec  https://hao.kevin.com.com/cgi-bin
     ProxyPassReverse  /mlslec  https://hao.kevin.com.com/cgi-bin
</IfModule>

<IfModule proxy_module>
ProxyPass /kevin http://www.kevin.com/ 
ProxyPassReverse /kevin http://www.kevin.com/
</IfModule>

<IfModule proxy_module>
ProxyPass /bobo http://192.168.1.10:8080/bobo/
ProxyPassReverse /bobo http://192.168.1.10:8080/bobo/
</IfModule>
  
==================================================
443埠的Proxypass跳轉
<IfModule proxy_module>
SSLProxyEngine On
  
ProxyPass  /xyy  https://bobo.kevin.com/pay/orderquery
ProxyPassReverse  /xyy  https://bobo.kevin.com/pay/orderquery
  
ProxyPass  /getsignkey   https://bobo.kevin.com/sandbox/pay/getsignkey
ProxyPassReverse  /getsignkey   https://bobo.kevin.com/sandbox/pay/getsignkey
  
ProxyPass  /authorize   https://shibo.kevin.com/connect/oauth2/authorize
ProxyPassReverse  /authorize   https://shibo.kevin.com/connect/oauth2/authorize
</IfModule>

相關文章