官术网_书友最值得收藏!

第一部分 準備篇

第1章 Apache基礎

1.1 Apache介紹

隨著網絡技術的普及和不斷發展,以及Web技術的不斷完善,Web服務已經成為互聯網上最重要的服務形式之一。原有的C/S模式正逐漸被B/S模式所取代。Apache是一種開源的HTTP服務器軟件,可以在大多數主流的計算機操作系統中運行(包括UNIX、Linux及Windows),再加上其支持多平臺且具有良好的安全性被廣泛使用。

1.1.1 Apache工作原理

Web系統由客戶端(瀏覽器)和服務器端兩部分組成。Web系統架構也被稱為B/S架構。最常見的Web服務器有Apache、IIS、Tomcat等,常用的瀏覽器有IE、Firefox、Maxthon等。當你想訪問一個網頁時,需要在瀏覽器的地址欄中輸入該網頁的URL(Uniform Resource Locator,簡稱為URL)地址,或者是通過超鏈接鏈接到該網頁。瀏覽器會向該網頁所在的服務器發送一個HTTP請求,服務器會對接收到的請求信息進行處理,然后將處理的結果返回給瀏覽器,最終將瀏覽器處理后的結果呈現給用戶。

作為世界上最流行的Web服務器,Apache遵循的同樣是HTTP協議,默認端口號為80,客戶端和服務器端的通信步驟如下:

(1)客戶端(瀏覽器)和Web服務器建立TCP連接,連接建立以后,向Web服務器發出訪問請求(如get)。根據HTTP協議,該請求中包含了客戶端的IP地址、瀏覽器的類型和請求的URL等一系列信息。

(2)服務器處理接收到的請求信息并將處理后的結果返回給客戶端。

(3)客戶端斷開與服務器的連接。

1.1.2 Apache的特點

因為Apache是開源的,所以得到了開源社區的大力支持,吸引了眾多優秀的開發人員參與其中,他們不斷開發出各種新的功能特性,并對存在的缺陷進行修復。經過多年的不斷完善,如今的Apache已經是最流行的Web服務器端軟件之一。Apache的特點是簡單、快速、高效和穩定。Apache服務器擁有以下特性:

?支持最新的HTTP/1.1通信協議。Apache是最先使用HTTP/1.1協議的Web服務器之一,它完全兼容HTTP/1.1協議并與HTTP/1.0協議向后兼容。Apache已為新協議所提供的全部內容做好了必要的準備。

?支持多計算機平臺。Apache幾乎可以在所有的計算機操作系統上運行,包括主流的UNIX、Linux及Windows操作系統。

?配置文件簡單,易操作。用戶可以通過直接修改Apache的配置文件信息來修改Apache,操作起來十分方便。

?支持實時監視服務器狀態和定制服務器日志。Apache在記錄日志和監視服務器自身運行狀態方面提供了很大的靈活性,可以通過Web瀏覽器來監視服務器的狀態,也可以根據自己的需要來定制日志。

?支持多種方式的HTTP認證。

?支持Web目錄修改。用戶可以使用特定的目錄作為Web目錄。

?支持CGI腳本,如Perl、PHP等。

?支持服務器端包含指令(SSI)。

?支持安全Socket層(SSL)。

?支持FastCGI。

?支持虛擬主機。即通過在一臺服務器上使用不同的主機名來提供多個HTTP服務。Apache支持基于IP、主機名和端口號三種類型的虛擬主機服務。

?跟蹤用戶會話。當用戶瀏覽基于Apache的Web站點時,可以通過Apache的mod_usertrack模塊對其進行跟蹤。

?支持動態共享對象。Apache的模塊可在運行時動態加載,這就意味著這些模塊可以被裝入服務器進程空間,從而減少系統的內存開銷。

?支持多進程。當負載增加時,服務器會快速生成子進程來處理,從而提高系統的響應能力。

?支持第三方軟件開發商提供的功能模塊。比如Apache加載mod_jserv模塊后可以支持Java Servlet,這樣就可以運行Java應用程序了。

?支持多線程和多進程混合模型的MPM。當MPM類型指定為worker時,由于是使用線程來處理,所以可以處理海量的請求,而系統資源的開銷要小于基于進程的服務器。

1.2 Windows下Apache的部署

1.2.1 Windows下Apache的安裝和配置

本節主要介紹在Windows操作系統中如何安裝和配置Apache服務器。首先應該到Apache官方網站(http://httpd.apache.org/download.cgi)下載安裝程序。當前的最新版本是2.3.5-alpha,這里我們以安裝Apache2.2.15為例進行介紹。安裝步驟如下:

(1)下載Apache的安裝包httpd-2.2.15-win32-x86-no_ssl.msi,雙擊進入安裝窗口,顯示當前Apache的版本信息,如圖1-1所示。

圖1-1 Apache HTTP Server的安裝界面

(2)點擊“Next”按鈕,進入Apache許可協議窗口,請仔細閱讀協議內容,如果同意此協議,則選中“I accept the terms in the license agreement”單選按鈕,如圖1-2所示。

圖1-2 Apache HTTP Server許可協議

(3)點擊“Next”按鈕,進入Apache HTTP服務器介紹窗口,如圖1-3所示。這里主要介紹Apache是什么、最新的版本信息,以及配置文件更改等,建議不太了解的讀者仔細閱讀。

圖1-3 Apache HTTP Server介紹

(4)點擊“Next”按鈕,進入服務器的相關信息設置頁面,如圖1-4所示。

圖1-4 設置Apache HTTP Server信息

相關設置選項的解釋如下:

?Network Domain指已經或者將要注冊的DNS域名。例如,如果你的DNS全稱是www. shopnc.net,一般可以省略域名前的www,只輸入shopnc.net部分。本地安裝可以默認輸入“localhost”字符串,或者127.0.0.1。

?Server Name是服務器DNS域名的全稱,例如www.phpchina.com。

?Administrator’s Email Address是服務器管理員的郵箱,它會在默認的錯誤提示頁面上顯示給用戶。

注意

這里所輸入的信息只是對Apache的一些基本配置,可以在安裝完成后通過編輯配置文件進一步配置。

?“for All Users, on Port 80, as a Service - Recommended”為默認選項,Apache默認任何人都可以訪問和監聽端口號為80的服務器。

注意

如果機器中的80端口被占用(IIS和Resin的默認端口號都是80),在安裝Apache之前需要先把它們的默認端口號改為非80,否則會因為端口號沖突而導致Apache無法正常啟動。

? “only for the Current User, on Port 8080, when started Manually”只允許當前用戶使用Apache,并且監聽端口號為8080的服務器,使用時需要手動啟動服務。

(5)點擊“Next”按鈕,選擇安裝類型,如圖1-5所示。如果選擇Typical(典型安裝),則安裝除開發模塊需要的源碼和庫以外的所有內容;如果選擇Custom(自定義安裝),則可以自己選擇要安裝的內容。這里我們選擇自定義安裝。

圖1-5 選擇安裝類型

(6)點擊“Next”按鈕,選擇要安裝的模塊,如圖1-6所示。點擊文字前面的圖標選擇是否安裝此模塊,如果沒有特殊要求,按默認設置安裝即可。Apache的默認安裝目錄是C:\Program Files\Apache Software Foundation\Apache2.2\,點擊“Change”按鈕自定義安裝目錄。

圖1-6 選擇安裝模塊和自定義安裝目錄

(7)點擊“Next”按鈕,進入安裝確認頁面,如圖1-7所示。如果想修改之前的信息,則可以點擊“Back”按鈕返回前面的步驟進行修改。

圖1-7 安裝確認頁面

后面的步驟非常簡單,按照提示進行操作即可完成安裝。安裝完成后我們可以測試一下Apache是否安裝成功。首先看一下系統托盤中是否出現了監視Apache服務的圖標,并且服務器是啟動狀態;然后打開瀏覽器,在地址欄輸入“http://localhost/”或http://127.0.0.1,如果顯示如圖1-8所示的頁面,說明Apache服務器已經安裝成功了。

圖1-8 Apache服務器安裝成功

Apache服務器安裝成功后,如果想對Apache進行配置,需要編輯安裝目錄下的conf子目錄下的httpd.conf文件。該文件是Apache服務器的配置文件,編輯完成后一定要重新啟動Apache服務器,這樣才會生效。

上面詳細地演示了Apache在Windows下安裝和配置的完整過程,非常簡單。Apache在Linux平臺上的安裝和配置的過程與此類似,限于篇幅,這里就不再重復演示。

1.2.2 啟動、停止和重新啟動Apache服務

在Windows操作系統中,Apache一般以服務的方式運行。在安裝Apache時,如果你選擇了“for all users”,Apache就會自動安裝為一個服務。如果選擇的是“only for the Current User”,可以在安裝后手動將Apache注冊為服務。注意,只有Administrators組的成員才能成功注冊服務。

使用Apache Service Monitor工具可以查看和管理你所在網絡上的所有機器上安裝的Apache服務的狀態,如圖1-9所示。為了使用Apache Service Monitor管理Apache服務,首先必須自動或手動安裝Apache服務。

圖1-9 用Apache Service Monitor管理Apache服務的狀態

可以在Apache安裝目錄的bin子目錄下使用如下命令安裝一個Apache服務。如果沒有指定服務名稱和配置文件,則在安裝時使用默認服務名稱Apache2.2,默認配置文件conf/httpd.conf。

        C:\Apache2.2\bin> httpd   -k   install

當在同一臺機器上裝有多個Apache服務時,必須為它們指定不同的名稱,這樣方便管理。可以使用下面的命令來指定服務的名稱,其中“ApacheShop”為指定的服務名稱。

        C:\Apache2.2\bin> httpd   -k   install   -n   ApacheShop

如果想為不同的服務指定不同的配置文件,可以在安裝時使用如下的命令來指定:

        C:\Apache2.2\bin> httpd  -k  install  -n  ApacheShop -f "C:/Apache2.2/conf/my.conf"

如果想移除一個Apache服務,可以使用如下的命令,默認移除的是名為Apache2.2的服務。

        C:\Apache2.2\bin> httpd   -k   uninstall

也可以移除指定名稱的服務,如下所示:

        C:\Apache2.2\bin> httpd   -k   uninstall   -n   ApacheShop

啟動、停止和重新啟動Apache服務的方法通常是使用Apache Service Monitor工具,另外也可以使用控制臺命令:NET START Apache2.2和NET STOP Apache2.2,或者使用Windows控制面板下的服務。

在啟動Apache服務之前,可以使用下面的命令來檢查配置文件的正確性。

        C:\Apache2.2\bin> httpd   -n   Apache2.2   -t

還可以通過命令行控制Apache服務。啟動一個已安裝的服務:

        C:\Apache2.2\bin> httpd   -k   start

停止一個已安裝的服務:

        C:\Apache2.2\bin> httpd   -k   stop

        C:\Apache2.2\bin> httpd   -k   shutdown

重新啟動一個運行中的服務,可以使用下面的命令強制其重新加載配置文件:

        C:\Apache2.2\bin> httpd   -k   restart

httpd命令非常重要,詳細介紹如下。

        httpd [-D name] [-d directory] [-f file]
              [-C "directive"] [-c "directive"]
              [-w] [-k start|restart|stop|shutdown]
              [-k install|config|uninstall] [-n service_name]
              [-v] [-V] [-h] [-l] [-L] [-t] [-S]

各參數選項的說明如下:

?-D parameter 設置參數parameter,它配合配置文件中的<IfDefine>字段,用于在服務器啟動和重新啟動時有條件地跳過或處理某些命令。

?-d serverroot 將ServerRoot指令的初始值設置為serverroot,它可以被配置文件中的ServerRoot指令覆蓋。

?-f config 在啟動中使用config作為配置文件。如果config不以“/”開頭,則它是相對于ServerRoot的路徑,其默認值是conf/httpd.conf。

?-k start|restart|graceful|stop|graceful-stop 發送信號使httpd啟動、重新啟動或停止。

?-C directive 在讀取配置文件之前,先處理directive的配置指令。

?-c directive 在讀取配置文件之后,再處理directive的配置指令。

?-e level 在服務器啟動時,設置LogLevel為level。用于在啟動時,臨時增加出錯信息的詳細程度,以幫助排錯。

?-E file 將服務器啟動過程中的出錯信息發送到文件file。

?-R directory 當在服務器編譯中使用SHARED_CORE規則時,它指定共享目標文件的目錄為directory。

?-h 輸出一個可用的命令行選項的簡要說明。

?-l 輸出一個靜態編譯在服務器中的模塊的列表。它不會列出使用LoadModule指令動態加載的模塊。

?-L 輸出一個指令的列表,其中包含了各指令的有效參數和使用區域。

?-M 輸出一個已經啟用的模塊列表,包括靜態編譯在服務器中的模塊和作為DSO動態加載的模塊。

?-S 顯示從配置文件中讀取并解析的配置結果(目前僅顯示虛擬主機的配置)。

?-t 僅對配置文件執行語法檢查。程序在語法解析檢查結束后立即退出,或者返回“0”(OK),或者返回非0值(Error)。如果還指定了“-D DUMP_VHOSTS”,則會顯示虛擬主機的詳細配置信息。

?-v 顯示httpd的版本,然后退出。

?-V 顯示httpd和APR/APR-Util的版本和編譯參數,然后退出。

?-X 以調試模式運行httpd。僅啟動一個工作進程,并且服務器不與控制臺脫離。

下列參數僅用于Windows平臺:

?-k install|config|uninstall 安裝Apache為一個Windows NT的服務;改變Apache服務的啟動方式;刪除Apache服務。

?-n name 指定Apache服務的名稱為name。

?-w 保持控制臺窗口的打開狀態,使得可以閱讀出錯信息。

1.2.3 Apache支持PHP語言

我們先從PHP的官方網站http://php.net/downloads.php下載PHP的安裝包(切記一定要下載編譯過的安裝包),這里我們以php-5.2.13-Win32版本為例進行講解。

下載完成后解壓安裝包,把解壓后的文件改名為“php5”并將其復制到C盤的根目錄下,然后進入php5的目錄,將文件php.ini-dist復制一份并改名為“php.ini”。在php.ini中需要修改以下幾個地方:

?設置擴展文件所在的目錄:在文件中找到extension_dir = "./",將其更改為extension_dir = "C:/php5/ext/"。

?開啟常用的擴展。

■;extension=php_gd2.dll

■;extension=php_mbstring.dll

■;extension=php_mcrypt.dll

■;extension=php_mysql.dll

■;extension=php_mysqli.dll

在httpd.conf配置文件中,分號(;)表示注釋該行內容。因此在需要開啟某項擴展功能時,只要刪除其前面的分號(;)即可。關于php.ini的詳細介紹請參考本書的第二部分。接下來編輯Apache的配置文件httpd.conf,主要修改以下幾個地方:

(1)加載用于處理PHP的模塊。找到#LoadModule vhost_alias_module modules/mod_vhost_alias.so代碼行,在下面添加以下代碼:

        LoadModule php5_module "C:/php5/php5apache2_2.dll"   ##加載php處理模塊

(2)在Apache中添加可識別PHP的MIME類型。找到AddType application/x-gzip .gz .tgz代碼行,在下面添加以下代碼:

        AddType application/x-httpd-php .php    ##php文件的MIME類型
        AddType application/x-httpd-source .phps    ##phps文件的MIME類型

(3)加載libmcrypt.dll和libmysql.dll類庫文件。在httpd.conf文件后面添加如下的加載文件代碼:

        LoadFile C:\php5\libmcrypt.dll   ##支持php_mcrypt.dll的類庫
        LoadFile C:\php5\libmysql.dll    ##支持php_mysql.dll的類庫

或者直接將C:\php5目錄下的libmcrypt.dll和libmysql.dll復制到C:\WINDOWS\system32目錄下。

(4)設置PHP的配置文件目錄。在httpd.conf文件的最后添加下面的代碼:

        PHPIniDir "C:/php5"   ##指定php.ini目錄

也可以把修改好的php.ini文件復制到C:/WINDOWS/目錄下。修改完成后保存文件,必須重啟Apache服務,以重新加載配置文件。接下來測試一下我們的配置是否成功,進入Apache的Web根目錄,新建一個名為“phpinfo.php”的文件,內容如下:

        <?php
        phpinfo();   //顯示服務器的配置信息
        ?>

打開瀏覽器,在地址欄中輸入http://localhost/phpinfo.php或http://127.0.0.1/phpinfo.php,如果出現如圖1-10的界面,則說明PHP環境已經搭建好了。

圖1-10 phpinfo()的顯示界面

1.3 httpd.conf深入剖析

Apache服務器的配置文件位于C:\Program Files\Apache Software Foundation\Apache2.2\conf\目錄下,一般會使用httpd.conf、access.conf和srm.conf三個配置文件來配置Apache服務器的行為。

httpd.conf提供了最基本的服務器配置,是對守護程序httpd如何運行的技術描述;srm.conf是服務器的資源映射文件,它告訴服務器各種文件的MIME類型,以及如何支持這些文件;access.conf用于配置服務器的訪問權限,控制不同用戶和計算機的訪問限制;這三個配置文件控制著服務器各個方面的特性,因此為了服務器的正常運行需要設置好這三個文件。

實際上,目前常用的Apache版本已經將原來的httpd.conf、srm.conf與access.conf中的所有配置參數均放在了配置文件httpd.conf中,只是為了兼容老版本(使用這三個配置文件的方式來源于NCSA-httpd)才使用了三個配置文件,而所提供的access.conf和srm.conf文件中沒有具體的配置。由于在新版本的Apache中,所有的設置都被放在了httpd.conf中,因此只需要調整這個文件中的配置即可。下面使用默認提供的httpd.conf為例,解釋Apache服務器的各個配置選項。不必因為它提供的配置參數太多而煩惱,基本上這些參數都很直觀,也可以在不加改動的情況下運行Apache服務器。但是,如果需要調整Apache服務器的性能,以及增加對某種特性的支持,就需要了解這些配置參數的含義。本節將對httpd.conf文件進行詳細的講解。

1.3.1 站點的基本配置

本節將重點介紹Apache對主站點進行配置的一些基本配置選項,如下所示。

?ServerRoot "/mnt/software/apache2":Apache軟件安裝的位置。其他指定的目錄如果沒有指定絕對路徑,則目錄是相對路徑。

?PidFile logs/httpd.pid:第一個httpd進程(所有其他進程的父進程)的進程號文件位置。?Listen 80:服務器監聽的端口號。

?ServerName www.clusting.com:80:主站點的名稱(網站的主機名)。

?ServerAdmin admin@clusting.com:管理員的郵件地址。

?DocumentRoot "/mnt/web/clusting":主站點的網頁存儲位置。

?DirectoryIndex index.html index.htm index.php:主頁文件的設置(本例將主頁文件設置為index.html、index.htm和index.php)。

1.3.2 服務器優化配置

Apache的主要優勢就是能更好地支持多處理器,在編譯時通過使用--with-mpm選項來決定Apache的工作模式。如果知道當前的Apache使用的工作機制,則可以通過httpd -l命令列出Apache的所有模塊,從而就可以知道其工作方式。

(1)prefork。如果httpd -l列出了prefork.c,則需要對下面的這段參數進行配置:

        StartServers 5             #啟動Apache時啟動的httpd進程個數
        MinSpareServers 5          #服務器保持的最小空閑進程數
        MaxSpareServers 10         #服務器保持的最大空閑進程數
        MaxClients 150             #最大并發連接數
        MaxRequestsPerChild 1000#每個子進程被請求服務多少次后被kill掉。0表示不限制,推薦設置為1000

在該工作模式下,服務器啟動后將啟動5個httpd進程(如果加上父進程,一共6個,通過ps -ax|grephttpd命令可以看到)。當有用戶請求連接時,Apache會使用一個空閑進程為該連接服務,同時父進程會fork一個子進程。直到內存中的空閑進程達到MaxSpareServers。該模式是為了兼容一些舊版本的程序。

(2)worker。如果httpd -l列出worker.c,則需要對下面的內容進行配置:

        StartServers 2             #啟動Apache時啟動的httpd進程個數MaxClients 150             #最大并發連接數MinSpareThreads 25         #服務器保持的最小空閑線程數MaxSpareThreads 75         #服務器保持的最大空閑線程數ThreadsPerChild 25         #每個子進程產生的線程數MaxRequestsPerChild 0      #每個子進程被請求服務多少次后被kill掉。0表示不限制,推薦設置為1000

該模式由線程來監聽客戶的連接。當有新客戶連接時,由其中的一個空閑線程接受連接。服務器在啟動后會啟動兩個進程,每個進程產生的線程數是固定的(由ThreadsPerChild決定),因此啟動時有50個線程。當50個線程不夠用時,服務器自動fork一個進程,再產生25個線程。

(3)perchild。如果httpd -l列出perchild.c,則需要對下面的內容進行配置:

        NumServers 5                         #服務器啟動時啟動的子進程數
        StartThreads 5                       #每個子進程啟動時啟動的線程數
        MinSpareThreads 5                    #內存中的最小空閑線程數
        MaxSpareThreads 10                   #內存中的最大空閑線程數
        MaxThreadsPerChild 2000              #每個線程最多被請求多少次后退出。0表示不受限制
        MaxRequestsPerChild 10000            #每個子進程服務多少次后被重新fork,0表示不受限制

該模式下,子進程的數量是固定的,線程數不受限制。當客戶端連接到服務器時,由空閑的線程提供服務。如果空閑的線程數不夠,子進程就會自動產生線程來為新的連接服務。該模式用于多站點服務器。

1.3.3 HTTP響應頭的信息配置

默認情況下,Apache安裝時會顯示版本號及操作系統的版本,甚至會顯示服務器上安裝了哪些Apache模塊。這些信息可能會被黑客利用,并且黑客還可以從中得知你所配置的服務器上的很多設置都是默認狀態。我們可以通過修改ServerTokens模塊對所顯示的內容進行設置。

ServerTokens用來設置http頭部返回的Apache版本信息。一般會帶有如下幾個參數,這些參數的含義和作用說明如下。

?Prod:僅軟件名稱,例如apache。

?Major:包括主版本號,例如apache/2。

?Minor:包括次版本號,例如apache/2.0。

?Min:僅Apache的完整版本號,例如apache/2.0.54。

?OS:包括操作系統類型,例如apache/2.0.54(Unix)。

?Full:包括Apache支持的模塊及模塊版本號,例如Apache/2.0.54 (Unix) mod_ssl/2.0.54 OpenSSL/0.9.7g。

1.3.4 持久性連接配置

在Apache的httpd.conf中,KeepAlive表示保持連接活躍,類似于MySQL的永久連接。換句話說,如果將KeepAlive設置為On,那么來自同一客戶端的請求就不需要再連接一次,避免每次請求都要新建一個連接而加重服務器的負擔。

KeepAlive的連接活躍時間當然是受KeepAliveTimeOut限制的。如果第二次請求和第一次請求之間超過了KeepAliveTimeOut的時間,第一次連接就會中斷,再新建第二個連接。所以,一般情況下,圖片較多的網站應該把KeepAlive設為On。但是KeepAliveTimeOut應該設置為多少秒就是一個值得討論的問題了。如果KeepAliveTimeOut設置的時間過短,例如設置為1秒,那么Apache就會頻繁地建立新連接,當然會耗費不少的資源;反過來,如果KeepAliveTimeOut設置的時間過長,例如設置為300秒,那么Apache中肯定有很多無用的連接會占用服務器的資源,也不是一件好事。所以,到底要把KeepAliveTimeOut設置為多少,則要根據網站的流量和服務器的配置而定。相關配置說明如下:

?KeepAlive On:開啟持久性連接功能。即當客戶端連接到服務器時,下載完數據后仍然保持連接狀態。

?MaxKeepAliveRequests 100:一個連接服務的最多請求次數。

?KeepAliveTimeout 30:測試一次連接中的多次請求傳輸之間的時間,如果服務器已經完成了一次請求,但一直沒有接收到客戶程序的下一次請求,在間隔超過了這個參數設置的值之后,服務器就斷開連接。默認值是15秒。

1.4 日志記錄

要有效地管理Web服務器,反饋服務器的活動、性能及出現的問題就很有必要。Apache HTTP服務器提供了非常全面而靈活的日志記錄功能。

1.4.1 日志的配置

Apache為管理員提供了很全面的日志管理工具來對服務器的活動進行事后分析。Apache提供了多種不同的記錄日志,但是對安全專業人士來說最重要的是訪問日志。這個靈活的工具還具有相當多的自定義功能,可以按照你的需要很方便地記錄盡可能多或少的日志,以保證有效的分析。

(1)ErrorLog file-path|syslog[:facility]

指定了當服務器遇到錯誤時記錄錯誤日志的文件。如果file-path不是一個以斜杠(/)開頭的絕對路徑,那么它會被認為是一個相對于ServerRoot的相對路徑。我們來看下面的示例:

        ErrorLog "logs/error.log"
        LogFormat format|nickname [nickname]

本指令的功能是定義訪問日志的記錄格式。例如:

        LogFormat "%h %l %u %t \"%r\" %>s %b" common

日志記錄中還包含將被原樣寫入日志的文本字符串及C風格的控制字符“\n”和“\t”,以實現換行與制表。文本中的引號和反斜杠應通過“\”來轉義。日志文件的具體格式如表1-1所示。

表1-1 日志文件的格式

(2)LogLevel

LogLevel用于調整記錄在錯誤日志中的信息的詳細程度。可以選擇表1-2所示的level,依照重要性降序排列。

表1-2 Level重要性等級列表

(3)CustomLog file|pipe format|nickname [env=[!]environment-variable]

CustomLog指令用來對服務器的請求進行日志記錄。可以指定日志的格式,也可以使用環境變量根據請求的特征來自由地組織日志。

1.4.2 錯誤日志

錯誤日志是最重要的日志文件,其存放位置取決于ErrorLog指令。如果服務器在啟動時或在運行中有問題,首先就應該查看錯誤日志。錯誤日志通常被寫入error.log文件中。錯誤日志的格式相對靈活,并且可以附加文字來描述。例如:

          [Fri Mar 12 23:04:192010] [error] [client 127.0.0.1] script 'E:/www/test.php'
    not found or unable to stat

各個參數的說明如下:

?[Fri Mar 12 23:04:192010]:錯誤發生的日期和時間。

?[error]:錯誤的級別,只有高于LogLevel指令指定級別的錯誤才會被記錄。

?[client 127.0.0.1]:是導致錯誤的IP地址。

?script 'E:/www/test.php' not found or unable to stat:錯誤的原因。

此例中,客戶訪問了一個不存在的文件,導致服務器產生了一個錯誤。服務器在記錄被訪問的文件時,用的是文件系統路徑,而不是Web路徑。

用戶可以增加或刪除錯誤日志的項,但是對于某些特殊請求,在訪問日志(access log)中也會有相應的記錄。例如,上述例子在訪問日志中也會有相應的記錄,其狀態碼是404。因為訪問日志也可以定制,所以可以從訪問日志中得到錯誤事件的更多信息。

1.4.3 訪問日志

訪問日志會記錄對Web服務器的所有請求,其存放文件和記錄的格式取決于CustomLog指令,LogFormat指令可以定義日志的內容格式。對于日志管理,首先必須產生訪問日志,然后才能分析日志,從而得到有用的統計信息。下面介紹如何配置服務器的訪問日志。

訪問日志的記錄格式非常靈活,使用風格很像C語言中的printf()函數的格式。可以通過下面介紹的幾種日志格式查看用于mod_log_config模塊的格式字符串。

(1)通用日志格式(Common Log Format)

          LogFormat "%h %l %u %t \"%r\" %>s %b" common
          CustomLog "logs/access.log" common

各參數的說明如下:

1)LogFormat定義了一種特定的記錄格式的字符串,并給它取了個別名叫common,其中的“%”表示服務器用某種信息替換,其他字符則不作替換。引號(")必須加反斜杠轉義,以避免被解釋為字符串的結束符。格式字符串還可以包含特殊的控制符,如換行符"\n"和制表符"\t"。

2)CustomLog定義了一個使用指定別名的日志文件,除非其文件名是以斜杠開頭的絕對路徑,否則其路徑就是相對于ServerRoot的相對路徑。

通用日志格式(CLF)的記錄格式被許多不同的Web服務器所采用,并被許多日志分析工具所識別,它產生的記錄字符串如下所示:

          127.0.0.1- - [12/Mar/2010:23:04:19 +0800] "GET /test.php HTTP/1.1" 404206

各參數的說明如下:

1)127.0.0.1:發送請求到服務器的客戶端IP地址。如果HostnameLookups設為On,則服務器會嘗試解析這個IP地址的主機名并替換此處的IP地址,但是不推薦這樣做,因為它會明顯地拖慢服務器,最好是用一個日志后續處理程序來判斷主機名,比如logresolve(logresolve是一個解析Apache訪問日志中IP地址的后處理程序,為了使對名稱服務器的影響降到最低,它擁有極為自主的內部散列表緩存,使每個IP值僅僅在第一次從日志文件中讀出時才被解析一次)。如果客戶端和服務器之間存在代理,那么記錄中的這個IP地址就是那個代理的IP地址,而不是客戶端的真實IP地址。

2)第一個"-":由客戶端identd進程判斷的RFC1413身份(identity),輸出中的符號"-"表示此處的信息無效。此信息通常很不可靠,不應該被使用,除非在嚴格控制的內部網絡中。只有將IdentityCheck指令設為On,Apache才會試圖獲取這項信息。

3)第二個"-":HTTP認證系統得到的訪問該網頁的客戶端標識(userid),環境變量REMOTE_USER會被設為該值并提供給CGI腳本。如果狀態碼是401,則表示客戶端未通過認證,此值沒有意義。如果網頁沒有設置密碼保護,則此項將是"-"。

4)[12/Mar/2010:23:04:19 +0800]:服務器完成請求處理時的時間,其格式是[日/月/年:時:分:秒 時區]。可以在格式字符串中使用 %{format}t來改變時間的輸出形式,其中的format與C語言標準庫中的strftime()用法相同。

5)"GET /test.php HTTP/1.1":客戶端發出的包含許多有用信息的請求行。可以看出,該客戶端的動作是GET,請求的資源是/test.php,使用的協議是HTTP/1.1。另外,還可以記錄其他信息,如格式字符串"%m %U%q %H"會記錄動作、路徑、查詢字符串及協議等。

6)404:服務器返回給客戶端的狀態碼。該信息非常有價值,因為它指示了請求的結果:成功響應(以2開頭),被重定向(以3開頭)、出錯(以4開頭),或產生了服務器端錯誤(以5開頭)。

7)206:返回給客戶端的不包括響應頭的字節數。如果沒有信息返回,則此項應該是"-",如果希望記錄為"0"的形式,則應該用%B。

(2)組合日志格式(Combined Log Format)

另一種常用的記錄格式是組合日志格式,形式如下:

        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
        CustomLog "logs/access.log" combined

這種格式與通用日志格式類似,但是多了兩個 %{header}i項,其中的header可以是任何請求頭。這種格式的記錄如下:

        127.0.0.1- - [13/Mar/2010:00:38:38 +0800] "GET /test.php HTTP/1.1" 404206 "-"
        "Mozilla/4.0   (compatible;   MSIE   7.0;   Windows   NT   6.1;   Trident/4.0;
    QQPinyinSetup  620;  SLCC2;  .NET  CLR  2.0.50727;  .NET  CLR  3.5.30729;  .NET  CLR
    3.0.30729; Media Center PC 6.0; InfoPath.2)"

其中,多出來的項是"-",它是"Referer"請求頭。此項指明了該請求是從哪個網頁提交過來的,如果內容為空,則此項顯示"-"。"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1;Trident/4.0; QQPinyinSetup 620; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2)"是"User-Agent"請求頭,此項是客戶端提供的瀏覽器識別信息。

1.5 虛擬主機

所謂虛擬主機是指在一臺機器上虛擬出多臺Web服務器。舉個簡單的例子,一家公司有多個不同域名的網站,它只需要購買一臺物理服務器,通過配置虛擬主機實現為多個站點提供Web服務,而訪問者通過輸入不同的域名來獲取想要的Web信息。

在Apache的配置文件中,通過<VirtualHost>區塊指令來識別不同的身份,也就是我們通常說的虛擬主機。Apache設置虛擬主機一般采用兩種方案:基于主機名的虛擬主機和基于IP地址的虛擬主機。這兩種方案可以單獨來使用,也可以混合使用,你可以根據實際工作需要來選擇一種適合自己的方案。

1.5.1 基于主機名的虛擬主機

要想在只有一個IP地址的服務器上支持多個網站,我們可以通過設置虛擬主機的主機名來進行區分。這樣就可以達到多個虛擬主機共享同一個IP地址的目的,同時也可以緩解IP地址不足的壓力。

基于主機名的虛擬主機的配置相對比較簡單,因為只需要配置DNS服務器,將每個主機名映射到正確的IP地址,然后配置Apache服務器,使其能辨識不同的主機名即可。

注意

在Apache服務器配置中創建一個虛擬主機并不會自動在你的DNS中對主機名進行相應的更新,你必須自己在DNS中添加域名來指向你的IP地址。否則,你的Web站點將無法訪問。你可以在本地的hosts文件中添加shop.example.com、bbs.example. com和myshop.example.com三個域名來進行測試,但這種方法僅適用于有這些hosts文件的主機。

現在可以通過域名shop.example.com來訪問你的主機,但如果你想在同一IP地址上添加一個新的虛擬主機,用域名bbs.example.com來訪問,那么需要在httpd.conf文件中加入以下代碼:

        NameVirtualHost *:80
        <VirtualHost *:80>
        ServerName shop.example.com
        ServerAlias myshop.example.com
        DocumentRoot C:/Apache2.2/htdocs/shop
        #這里可以添加其他指令
        </VirtualHost>
        <VirtualHost *:80>
        ServerName bbs.example.com
        DocumentRoot C:/Apache2.2/htdocs/bbs
        #這里可以添加其他指令
        </VirtualHost>

因為星號匹配所有的IP地址,所以主服務器不接收任何請求。上例中shop.example.com首先出現在配置文件中,所以它擁有最高的優先級,可以認為是默認服務器或主服務器。這意味著,如果一個請求不能與某個ServerName指令相匹配,它將會由第一個<VirtualHost>區塊來提供服務。

NameVirtualHost指定了主機的IP地址和端口號(默認80端口可省略),如果想讓主機可以在所有地址上運行,可以使用"*"作為NameVirtualHost的參數。每個<VirtualHost>區塊對應的是一個虛擬主機的配置。<VirtualHost>的參數與NameVirtualHost的參數必須是一致的。在每個<VirtualHost>區塊中,只要包含一個指定服務主機的名稱的ServerName指令和一個指向主機內容所在文件系統目錄的DocumentRoot指令即可。

由于一些特殊需要,很多服務器希望能通過多個域名來訪問。我們可以通過ServerAlias指令來指定多個域名,多個域名之間使用空格來區分,例如:

        ServerAlias myshop.example.com othershop.example.com

也可以建立一個默認虛擬主機來接受所有客戶端請求,并對主機進行一些錯誤處理,例如找不到主機。

        NameVirtualHost *
        <VirtualHost *>
        ServerName default
        DocumentRoot C:/Apache2.2/htdocs/shop
        ErrorDocument 404 C:/Apache2.2/htdocs/shop/error.html
        </VirtualHost>

當然,也可以用一個固定的IP地址來代替NameVirtualHost和<VirtualHost>指令中的"*",以達到一些特定的目的。然而,當IP地址無法確定時,使用"*"是很方便的,例如,你的ISP給你配置的是動態IP地址,而你又使用了某種動態域名解析系統。因為"*"匹配任何IP地址,所以在這種情況下,無論IP地址如何變化,你都不需要另外進行配置。

1.5.2 基于IP地址的虛擬主機

在一個擁有多個IP地址的服務器上,如果想要通過多個IP地址請求來提供相同的內容,可以配置基于每個IP地址的虛擬主機來達到這個目的。服務器中基于IP地址的各個虛擬主機必須擁有不同的IP地址。

例如,在同一臺服務器上使用兩個IP地址(192.168.0.2和192.168.0.3分別對應shop. example.com和myshop.example.com)請求來獲取相同內容,我們以此為例來介紹基于IP地址的虛擬主機配置。在httpd.conf中加入以下代碼:

        NameVirtualHost 192.168.0.2
        NameVirtualHost 192.168.0.3
        <VirtualHost 192.168.0.2>
        ServerName shop.example.com
        DocumentRoot C:/Apache2.2/htdocs/shop
        #這里可以添加其他指令
        </VirtualHost>
        <VirtualHost 192.168.0.3>
        ServerName myshop.example.com
        DocumentRoot C:/Apache2.2/htdocs/shop
        #這里可以添加其他指令
        </VirtualHost>

如果存在主服務器,那么所有沒有出現在任何一個<VirtualHost>區塊中的請求(例如對localhost的請求)都會由主服務器來提供服務。

1.6 URL重寫

隨著Web技術的發展,URL的展現形式也越來越多樣化,比如說現在比較流行網頁靜態化,這樣一方面可以加快訪問速度,另外一方面也可以更好地被搜索引擎錄入。并不是你看到的所有靜態網頁都是通過靜態化生成的,這可能只是一種欺騙手段,可能是運用了另一種更高效的緩存技術。可以通過URL重寫來達到欺騙的目的,Apache提供了一個mod_rewrite模塊來實現URL的重寫功能。

1.6.1 mod_rewrite模塊

mod_rewrite模塊提供了一種靈活而且強大的URL操作機制,可以使服務器操作整個URL。它基于正則表達式分析器的重寫引擎來實時重寫URL請求。mod_rewrite模塊中的指令分為服務器級和目錄級,前者的作用域是該服務下的所有網站,指令在httpd.conf中配置;后者只對.htaccess文件所在的目錄有效,并在.htaccess中進行配置。重寫操作包括內部子處理、內部代理處理和外部請求轉向。其主要的工作步驟如下:

(1)接受一個具有一定規則的URL請求

(2)按照設定的規則進行匹配,匹配成功則會生成匹配結果。

(3)通過匹配結果進行下一步操作。

mod_rewrite模塊默認是不開啟的,需要先開啟它。方法是先打開httpd.conf,找到#LoadModule rewrite_module modules/mod_rewrite.so,去掉前面的注釋,然后保存即可。

下面我們來實踐一個簡單的例子,首先在DocumentRoot目錄下新建一個名為shop的文件夾,然后在該目錄下創建兩個文件,文件內容分別如下所示。

?舊文件

        old.html
        <html>
        <head>URL重寫測試</head>
        <body>
        我是舊的文件
        </body>
        </html>

?新文件

        new.html
        <html>
        <head>URL重寫測試</head>
        <body>
        我是新的文件
        </body>
        </html>

通過瀏覽器訪問http://localhost/shop/old.html和http://localhost/shop/new.html顯示的結果都是正常的,接下來我們對old.html的URL進行重寫,在shop目錄下創建名為.htaccess的文件,內容如下:

        #開啟重寫引擎
        RewriteEngine On
        #重寫URL規則
        RewriteRule    ^old\.html$   new.html

我們再次訪問http://localhost/shop/old.html時,頁面顯示的不是old.html的內容,而是new.html的內容。

1.6.2 常用指令

在實際工作中為了提高工作效率,也可以通過Apache提供的一些指令來實現所需的各種功能,下面就一些常用指令進行詳細講解。

1. RewriteEngine指令

RewriteEngine指令用來開啟或關閉URL重寫引擎。如果設置為Off,Apache在運行時則不執行URL重寫操作。RewriteEngine指令語法如下:

        RewriteEngine On|Off

注意 如果虛擬主機中需要URL的重寫功能,則必須設置RewriteEngine On指令。

2. RewriteBase指令

RewriteBase指令用來設置URL重寫的根目錄。如果不設置該指令,則默認是.htaccess文件所在的目錄。RewriteBase指令語法如下:

          RewriteBase URL-path

例如,要想通過訪問舊的URL地址(http://localhost/shop/old.html)來顯示新的URL地址(http://localhost/shop/new.html)下的頁面內容,則需要在shop目錄下的.htaccess文件(如果.htaccess文件不存在,則需要手動創建)中設置下面的指令:

          # /shop/.htaccess -- /shop目錄的配置文件
          #開啟重寫引擎
          RewriteEngine On
          # URL重寫目錄,“/”為當前目錄
          RewriteBase   /
          # 重寫規則
          RewriteRule    ^old\.html$   new.html

注意

保存后需要重啟Apache服務器。shop目錄下必須存在new.html文件,否則會提示404錯誤。

3. RewriteCond指令

RewriteCond指令定義了一個重寫規則條件。在一個RewriteRule指令之前可以有一個或多個RewriteCond指令。重寫規則僅在當前URI與Pattern匹配并且滿足此條件時才會起作用。RewriteCond指令的語法如下:

          RewriteCond TestString CondPattern [flags]

TestString是一個純文本的字符串,還可以包含下列的可擴展部分:

(1)RewriteRule反向引用

引用形式:$N(0 <= N <= 9)。引用當前(帶有若干RewriteRule指令的)RewriteCond中與Pattern匹配的分組成分。

(2)RewriteCond反向引用

引用形式:%N(1 <= N <= 9)。為當前RewriteCond條件中最后一個與pattern匹配的分組部分提供訪問的引用形式。

(3)服務器變量

引用形式:%{ NAME_OF_VARIABLE }。NAME_OF_VARIABLE可以是表1-3中的任意一個字符串。

表1-3 NAME_OF_VARIABLE指定字符串列表

這些變量都對應于類似命名的HTTP MIME頭,Apache服務器的C變量或Unix系統中的struct tm字段,其中大多數變量在其他手冊或CGI規范中都有說明。還需要注意以下幾點:

1)變量SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的,即Apache服務器內部的request_rec結構中的filename字段的值。第一個變量也稱為CGI變量名,而第二個變量恰好對應的是REQUEST_URI(包含request_rec中uri字段的值)。

2)%{ENV:variable}中的variable可以是任意環境變量,可通過查找Apache內部結構或通過函數getenv()從Apache服務器進程中來獲得。

3)%{SSL:variable} 中的variable可以是一個SSL環境變量的名字,無論是否加載mod_ssl模塊都可以使用,如果沒有加載,則為空字符串,比如%{SSL:SSL_CIPHER_USEKEYSIZE}將會演變為128。

4)%{HTTP:header}中的header可以是任意HTTP MIME頭的名稱,可以通過發送一個HTTP請求來獲得,比如%{HTTP:Proxy-Connection}是HTTP header Proxy-Connection的值。

5)%{LA-U:variable}可用于查找在執行一個內部(基于URL的)子請求后確定的最終值。可以用于重寫一個目前未知但是會在之后的過程中設置的變量。例如,需要在服務器級的配置(httpd.conf文件)中根據REMOTE_USER變量進行重寫,就必須使用%{LA-U:REMOTE_USER},因為此變量是在URL重寫(mod_rewrite)操作之后的授權階段設置的。另一方面,因為mod_rewrite是在API命名修正階段實現對目錄級(.htaccess文件)的配置的,而授權階段優先于此階段,所以在這種情況下使用%{REMOTE_USER}。

6)%{LA-F:variable}用于在執行一個內部(基于文件名的)子請求后確定變量的最終值。在大多數情況下,與上述的LA-U是相同的。

7)CondPattern是一個條件模板,即一個與TestString進行匹配的正則表達式。它是一個與Perl兼容的正則表達式,它有如下兩個特點:

?可以給模式字符串加一個"!"前綴,指定一個非匹配模式。

?有一些特殊的CondPatterns變種,它們并不是真正的正則表達式字符串,主要有如下形式:

■'<CondPattern':小于字符串CondPattern。將CondPattern作為一個普通的字符串并與TestString根據字典順序進行比較,如果TestString小于CondPattern,則為真。

■'>CondPattern':大于字符串CondPattern。將CondPattern作為一個普通的字符串與TestString按字典順序進行比較,如果TestString大于CondPattern,則為真。

■'=CondPattern':等于字符串CondPattern。將CondPattern作為一個普通的字符串與TestString按字典順序進行比較,如果TestString等于CondPattern(兩個字符串完全相等),則為真。

■'-d':判斷是否是目錄。把TestString作為一個路徑名并測試它是否為一個已存在的目錄。

■'-f':判斷是否為文件。把TestString作為一個路徑名并測試它是否為一個已存在的文件。

■'-s':判斷是否為非空的文件。把TestString作為一個路徑名并測試它是否為一個已存在的且大小大于0的文件。

■'-l':判斷是否為符號鏈接。把TestString作為一個路徑名并測試它是否為一個已存在的符號連接。

■'-x':判斷是否為有可執行權限的文件。把TestString作為一個路徑名并測試它是否為一個已存在的并且具有可執行權限的文件。該權限由操作系統檢測。

■'-F':判斷是否是通過子請求訪問存在的文件。檢查TestString是否為一個有效的文件,而且可以在服務器當前的訪問控制配置下被訪問。它使用一個內部子請求來做檢查,由于會降低服務器的性能,所以請謹慎使用!

■'-U':判斷是否是通過子請求訪問存在的URL。檢查TestString是否為一個有效的URL,而且可以在服務器當前的訪問控制配置下被訪問。它使用一個內部子請求來做檢查,由于會降低服務器的性能,所以請謹慎使用!

注意 這些測試都可以用驚嘆號作前綴('!')來實現相反條件的測試。

另外,RewriteCond指令的后面可選擇添加flags標記,多個標記之間以逗號分隔。目前只有2個標記,分別是:NC(不區分大小寫)和OR(與下一個條件建立或的關系)。當RewriteCond指令的判斷條件為真時,它下面的RewriteRule指令才會被執行。例如,根據客戶端使用的瀏覽器的不同來顯示不同的頁面,設置內容如下:

        #開啟重寫引擎
        RewriteEngine on
        #如果是火狐瀏覽器,則顯示homepage.max.html
        RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
        RewriteRule ^/$ /homepage.max.html [L]
        #如果是IE瀏覽器,則顯示homepage.min.html
        RewriteCond %{HTTP_USER_AGENT} ^MSIE.*
        RewriteRule ^/$ /homepage.min.html [L]
        #不滿足上面兩種條件,則顯示homepage.std.html
        RewriteRule ^/$ /homepage.std.html [L]

4. RewriteRule指令

RewriteRule指令用于為重寫引擎定義重寫規則。我們可以同時配置多個RewriteRule指令,但是一定要注意它們的先后順序。RewriteRule指令的語法如下:

        RewriteRule Pattern Substitution [flags]

Pattern用于重寫當前URL的正則表達式,Substitution是與Pattern匹配成功后用來替換的字符串。除了純文本外,還可以包含:

(1)對Pattern的反向引用($N)。

(2)對最后匹配的RewriteCount的反向引用(%N)。

(3)規則條件測試字符差(%{VARNAME})中的服務器變量。

flags(可選)用于重寫規則標記,多個標記之間用半角逗號(,)分隔。重寫規則標記的相關參數如下所示。

(1)C:用于關聯下一條規則。如果當前規則匹配成功,則該標記不起作用,否則與之關聯的規則都會被跳過而不進行匹配。

(2)CO=NAME:VAL:domain[:lifetime[:path]]':用戶在客戶端設置一個cookie。NAME是cookie的名稱,VAL是cookie的值。domain是cookie的域,lifetime(可選)是cookie的有效期(分鐘),path(可選)是cookie的路徑。

(3)E=VAR:VAL:用于設置環境變量。VAR是變量名,VAL是變量的值。

(4)F:用于強制禁止當前URL。反饋一個HTTP響應碼403(被禁止的)。

(5)G:用于強制放棄當前URL。反饋一個HTTP響應碼410(已放棄的)。

(6)H:用于強制指定目標文件的內容處理器為Content-handler。

(7)L:用于停止重寫操作,并且不再應用其他的重寫規則。

(8)N:用于重新執行重寫操作。

(9)NC:使Pattern忽略大小寫。在Pattern與當前URL匹配時,'A-Z'和'a-z'沒有區別。

(10)NE:用于阻止mod_rewrite對重寫結果應用常規的URI轉義規則。一般情況下,特殊字符('%','$',';'等)會被轉義為等值的十六進制編碼('%25', '%24', '%3B'等),使用此標記可以阻止這些符號的轉義。

(11)NS:用于跳過對內部子請求的重寫規則。

(12)P:用于substitution部分在內部作為代理請求被強制發送,并中斷重寫處理,然后交給mod_proxy模塊(mod_proxy模塊必須是已啟用狀態)。

(13)PT:強制重寫引擎將request_rec內部結構中的uri字段設置為filename字段的值,使得RewriteRule指令的輸出內容(從不同的URI轉換到filename的)能夠被Alias、ScriptAlias、Redirect等指令進行后續處理。

(14)QSA:強制重寫引擎在已有的substitution字符串中追加一個查詢字符串,而不是替換它。

(15)R:如果Substitution的前綴是以http://thishost[:thisport]/開頭的,則強制執行外部重定向。如果沒有指定code,則產生一個HTTP響應碼302(臨時性移動的)。如果想使用300~400范圍內的其他響應碼,在此指定即可。

(16)S=num:強制重寫引擎跳過當前規則之后的num個規則。

(17)T=MIME-type:強制目標文件的MIME類型。

5. RewriteLog指令

RewriteLog指令設置用于記錄所有重寫操作的日志文件的名稱。如果此文件名不以斜杠(/)開頭,則它是相對于Server Root的,此指令應該在每個服務器級別的配置中僅出現一次。RewriteLog指令的語法如下:

          RewriteLog file-path

注意

如果要關閉對重寫操作的記錄,可以刪除或注釋掉RewriteLog指令,或者設置RewriteLogLevel的值為0。

6. RewriteLogLevel指令

RewriteLogLevel指令設置重寫引擎日志的詳細程度的級別。默認為0,意味著不記錄;9或更大的值則意味著記錄所有操作。RewriteLogLevel指令的語法如下:

          RewriteLogLevel Level

注意

較高的Level值會使Apache服務器的速度急劇下降!大于2的Level值只用于調試目的!

1.7 實戰案例

1.7.1 防止圖片盜鏈

所謂盜鏈是指服務提供商自己不提供服務的內容,而是通過技術手段直接在自己的網站上向最終用戶提供其他服務提供商的服務內容,以騙取用戶的瀏覽和點擊率。受益者不提供資源或提供很少的資源,而真正的服務提供商卻得不到任何的收益。像圖片、視頻等這些比較大的文件都有可能成為被盜的對象。一旦文件被盜,就會增加服務器的流量,影響網站的訪問速度。雖然我們不能100%的保護這些文件不被別人盜用,但可以通過HTTP Referer進行限制。使用Apache可以很方便地進行設置。假設主機域名為www.example.com,在文件.htaccess中的配置如下:

        RewriteEngine on
        RewriteCond %{HTTP_REFERER} !^$ [NC]
        RewriteCond %{HTTP_REFERER} ! http://www.example.com [NC]
        RewriteCond %{HTTP_REFERER} ! http://www.google.cn [NC]
        RewriteCond %{HTTP_REFERER} ! http://www.baidu.com [NC]
        RewriteRule .*\.(gif|jpg)$ http://www.example.com/default.jpg [R,NC,L]

該配置的說明如下:

?RewriteCond %{HTTP_REFERER} !^$ [NC]

允許HTTP_REFERER為空時訪問,即允許用戶在瀏覽器地址欄中直接輸入圖片地址時顯示圖片。一般來說這個選項是可選的,建議這樣設置。如果將HTTP_REFERER強制限制不能為空,那么當用戶通過代理服務器訪問時,可能會導致一些問題。

?RewriteCond %{HTTP_REFERER} !www.example.com [NC]

設置允許訪問的HTTP_REFERER來源,包括自身站點,以及Baidu、Google、Yahoo!等。

?RewriteRule .*\.(gif|jpg)$ http://www.example.com/default.jpg [R,NC,L]

設置圖片被盜鏈時用于替換的圖片,如果有圖片被盜鏈,顯示的是default.jpg。注意,默認圖片所在的路徑最好跟配置文件不在同一目錄下,圖片越小越好。如果不想設置替換圖片,可以使用下面的語句:

        RewriteRule .*\.(gif|jpg)$ - [F]

?NC、R、L、F標記解釋

■NC:不區分大小寫。

■R:強制重定向。

■L:立即停止重寫操作。

■F:強制禁止URL。

1.7.2 Apache偽靜態

頁面靜態化是現在比較流行的一種頁面處理技術,靜態頁面既能提高訪問速度,也能被搜索引擎更好地抓取。比較常用的方式有兩種:一種是通過程序來生成靜態化頁面,另一種是通過Apache的rewrite模塊來實現,這里我們以Windows下的Discuz7.2為例進行介紹。Discuz 7.2的安裝見本書的第22章。

首先,進入Discuz后臺,依次打開“全局”→“優化設置”→“搜索引擎優化”菜單選項,如圖1-11所示。

圖1-11 Discuz7.2后臺的全局優化設置

在“URL靜態化”區塊中,選中需要靜態化的頁面,點擊下方的“提交”按鈕即可。這時直接通過靜態頁面來訪問會報錯,我們還需要在Apache的配置文件中進行相關的設置。

打開httpd.conf,找到#LoadModule rewrite_module modules/mod_rewrite.so并去掉前面的注釋(#),然后在文件的最后添加以下代碼:

        <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^(.*)/archiver/((fid|tid)-[\w\-]+\.html)$ $1/archiver/index.php?$2
        RewriteRule
        ^(.*)/forum-([0-9]+)-([0-9]+)\.html$ $1/forumdisplay.php?fid=$2&page=$3
        RewriteRule
        ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/viewthread.php?tid= $2&extra=page\%3D$4&page=$3
        RewriteRule ^(.*)/space-(username|uid)-(.+)\.html$ $1/space.php?$2=$3
        RewriteRule ^(.*)/tag-(.+)\.html$ $1/tag.php?name=$2
        </IfModule>
        保存修改好的文件,重啟Apache服務就可以了。

1.7.3 用戶訪問權限設置

在維護網站時,為了安全起見,一些重要的目錄是不允許普通用戶訪問的,我們可以給這些目錄設置一個指定用戶才能訪問的權限。Apache的mod_auth_basic模塊就提供了相關的功能,我們以Windows下的Aapche2.2.*為例來實現此功能。

假設我們現在有shop和bbs兩個目錄,shop目錄只能通過用戶user1來訪問,bbs目錄則只能通過用戶user2來訪問,步驟如下:

(1)通過命令創建用戶user1和user2,如下所示:

        C:\Apache2.2\bin>htpasswd -c C:/Apache2.2/htaccess user1
        C:\Apache2.2\bin>htpasswd C:/Apache2.2/htaccess user2

使用htpasswd命令創建用戶,-c指定創建一個新的文件,C:/Apache2.2/htaccess是新文件的目錄,user1是用戶名,創建完成后,可以到C:/Apache2.2目錄下打開htaccess文件查看用戶信息,如下所示:

        user1:$apr1$aW5HEi2.$qUADQLr7cVGehl4NfWMFi1
        user2:$apr1$O8GattjZ$aGG.ix2qHl3Da5FGaQYhF0

(2)打開httpd.conf文件,找到下面的3個模塊:

?LoadModule auth_basic_module modules/mod_auth_basic.so

?LoadModule authn_file_module modules/mod_authn_file.so

?LoadModule authz_user_module modules/mod_authz_user.so

請確定上面3個加載模塊的命令前的注釋是去掉的。找到#Include conf/extra/httpd-autoindex.conf,去掉前面的注釋(#)。在httpd-autoindex.conf中配置用戶訪問權限,修改完成后保存httpd.conf文件。

(3)進入conf/extra/目錄,對文件httpd-autoindex.conf進行編輯,添加如下的代碼:

        <Directory "C:/Apache2.2/htdocs/shop/">
            Options Indexes MultiViews
            AllowOverride None
            Order allow,deny
            Allow from all
        </Directory>
        <Directory "C:/Apache2.2/htdocs/shop/">
            AuthType Basic
            AuthName "please put into your name and password"
            AuthUserFile C:/Apache2.2/htaccess
            Require user user1
        </Directory>
        <Directory "C:/Apache2.2/htdocs/bbs/">
            Options Indexes MultiViews
            AllowOverride None
            Order allow,deny
            Allow from all
        </Directory>
        <Directory "C:/Apache2.2/htdocs/bbs/">
            AuthType Basic
            AuthName "please put into your name and password"
            AuthUserFile C:/Apache2.2/htaccess
            Require user user2
        </Directory>

代碼中的關鍵部分說明如下:

?AuthType:指定認證類型模型,一般常用的AuthType是“Basic/Digest”。這個認證需要用到認證模塊mod_auth_basic/mod_auth_digest、認證支持模塊mod_authn_file和認證授權模塊mod_authz_user。

?AuthName:指定驗證登錄框的提示信息。

?AuthUserFile:指定驗證信息文件的存放目錄。

?Require user:指定允許訪問的用戶,多個用戶之間用空格分隔。

編輯完成后保存,重啟Apache服務。

(4)輸入網址http://localhost/shop進行測試,測試結果如圖1-12所示。

圖1-12 提示用戶輸入用戶名和密碼

如果輸入有權限的用戶名user1和密碼,則進入訪問目錄,如圖1-13所示。

圖1-13 驗證成功后進入顯示頁面

如果用戶名或密碼錯誤,訪問該目錄時會被拒絕。

1.8 小結

本書開篇之所以講Apache是因為考慮到它的基礎性及關鍵性,這是開始PHP之旅之前必修的一門課。本章主要講解了Apache在實際工作中的應用,并對Apache配置文件的書寫及其中的關鍵性模塊進行了闡述。

如果大家對Apache還有更濃厚的興趣,可以參閱Apache相關的專業書籍,這對以后從事基于服務器方面的管理和開發會有很大的幫助。

主站蜘蛛池模板: 潢川县| 黔东| 浮梁县| 桐乡市| 绥芬河市| 成武县| 正阳县| 昭平县| 象山县| 手游| 和顺县| 舟曲县| 昌都县| 花垣县| 涟水县| 青龙| 炉霍县| 乌苏市| 东兴市| 大同市| 色达县| 南开区| 南澳县| 民勤县| 保康县| 临城县| 册亨县| 涿州市| 阳曲县| 顺平县| 灯塔市| 安福县| 穆棱市| 成武县| 新泰市| 梧州市| 襄樊市| 栾川县| 临武县| 葵青区| 安福县|