Apache認證和授權


身份驗證是驗證存取者是否是他們所聲稱的人的任何過程。授權是允許存取者進入他們想去的地方或獲得他們想要的資訊的過程。

如果您的網站上的資訊僅對一小部分人使用,下面這些技巧將幫助您確保看到這些網頁的人員是您想要檢視的人。

本文還將介紹保護大多數人將要使用的網站部分的「標準」方法。

1. 前提條件

本文中討論的指令需要在主伺服器組態檔案(通常在<Directory>部分中)或每目錄組態檔案(.htaccess檔案)中。

如果計劃使用.htaccess檔案,則需要具有允許在這些檔案中放置身份驗證指令的伺服器組態。這是通過AllowOverride指令完成的,該指令指定可以在每個目錄組態檔案中放入哪些指令(如果有)。

由於我們在這裡談論身份驗證,所以需要如下所示的AllowOverride指令:

AllowOverride AuthConfig

或者,如果您只是將指令直接放在主伺服器組態檔案中,需要具有該檔案的寫入許可權。
並且您需要了解伺服器的目錄結構,以便瞭解某些檔案的儲存位置。這應該不是非常困難,當到達那一點時,我們會盡力說清楚。

還需要確保模組mod_authn_coremod_authz_core已內建到httpd二進位制檔案中或由httpd.conf組態檔案載入。這兩個模組都提供核心指令和功能,這些指令和功能對於在Web伺服器中組態和使用身份驗證和授權至關重要。

2. 組態工作

以下是密碼保護伺服器上目錄的基礎知識。

首先,您需要建立一個密碼檔案。具體如何執行此操作將取決於您選擇的身份驗證提供程式。稍後會詳細介紹。首先,我們將使用文字密碼檔案。

此檔案應放置在無法從Web存取的位置。這樣人們就無法下載密碼檔案。例如,如果您的文件是由/usr/local/apache/htdocs提供的,則可能需要將密碼檔案放在/usr/local/apache/passwd中。

要建立該檔案,請使用Apache附帶的htpasswd實用程式。這將位於安裝Apache的任何位置的bin目錄中。如果已從第三方軟體包安裝Apache,則它可能位於您的執行路徑中。

要建立檔案,輸入以下命令:

$ htpasswd -c /usr/local/apache/passwd/passwords rbowen

htpasswd會要求您輸入密碼,然後再次要求您輸入密碼進行確認:

# htpasswd -c /usr/local/apache/passwd/passwords rbowen
New password: mypassword
Re-type new password: mypassword
Adding password for user rbowen

如果htpasswd不在你的路徑中,則需要輸入檔案的完整路徑才能執行它。使用預設安裝時,它位於/usr/local/apache2/bin/htpasswd

接下來,需要組態伺服器以請求密碼並告知伺服器允許哪些使用者存取。可以通過編輯httpd.conf檔案或使用.htaccess檔案來執行此操作。例如,如果您希望保護目錄/usr/local/apache/htdocs/secret,則可以使用以下指令,這些指令放在檔案/usr/local/apache/htdocs/secret/.htaccess中,或放入httpd.conf<Directory "/usr/local/apache/htdocs/secret">部分中。

AuthType Basic
AuthName "Restricted Files"
# (Following line optional)
AuthBasicProvider file
AuthUserFile "/usr/local/apache/passwd/passwords"
Require user rbowen

下面分別看一看每個指令。AuthType指令選擇用於驗證使用者身份的方法。最常用的方法是Basic,這是mod_auth_basic實現的方法。但是,請務必注意,基本身份驗證會將密碼從用戶端傳送到未加密的伺服器。因此,除非帶有mod_ssl,否則此方法不應用於高度敏感的資料。Apache支援另一種身份驗證方法:AuthType Digest。此方法由mod_auth_digest實現,旨在更安全。這不再是這種情況,應該使用mod_ssl加密連線。

AuthName指令設定要在身份驗證中使用的Realm。領域有兩個主要功能。首先,用戶端經常將此資訊作為密碼對話方塊的一部分呈現給使用者。其次,用戶端使用它來確定為給定的已驗證區域傳送的密碼。

因此,一旦用戶端在「受限檔案」區域中進行了身份驗證,它將自動為同一伺服器上標有「受限檔案」域的任何區域重試相同的密碼。因此,通過讓多個受限區域共用同一個域,可以防止使用者多次提示輸入密碼。當然,出於安全原因,只要伺服器的主機名發生更改,用戶端就始終需要再次詢問密碼。

在這種情況下,AuthBasicProvider是可選的,因為file是此指令的預設值。如果要為身份驗證選擇其他源,則需要使用此指令,例如mod_authn_dbmmod_authn_dbd

AuthUserFile指令設定htpasswd建立的密碼檔案的路徑。如果需要填入大量使用者,則搜尋純文字檔案以在每個請求上對使用者進行身份驗證可能會非常慢。Apache還能夠將使用者資訊儲存在快速資料庫檔案中。mod_authn_dbm模組提供AuthDBMUserFile指令。可以使用dbmmanagehtdbm程式建立和操作這些檔案。Apache模組資料庫中的第三方模組提供了許多其他型別的身份驗證選項。

最後,Require指令通過設定允許存取伺服器的此區域的使用者來提供進程的授權部分。

3. 允許多人進入

上面的指令只允許一個人(特別是使用者名為rbowen的人)進入目錄。在大多數情況下,不止一個人進入存取。這種情況下就要使用AuthGroupFile了。

如果要允許多個人進入,則需要建立一個組檔案,該組檔案將組名與該組中的使用者列表相關聯。此檔案的格式非常簡單,您可以使用自己喜歡的編輯器建立它。該檔案的內容如下所示:

GroupName: rbowen dpitts sungo rshersey

這只是一個由空格分隔的長行中的成員列表。要將使用者新增到現有密碼檔案,請鍵入:

htpasswd /usr/local/apache/passwd/passwords dpitts

您將獲得與以前相同的響應,但它將附加到現有檔案,而不是建立新檔案。(這裡是使用-c來建立一個新的密碼檔案)。

現在,需要修改.htaccess檔案或<Directory>塊,如下所示:

AuthType Basic
AuthName "By Invitation Only"
# Optional line:
AuthBasicProvider file
AuthUserFile "/usr/local/apache/passwd/passwords"
AuthGroupFile "/usr/local/apache/passwd/groups"
Require group GroupName

現在,如果他們輸入正確的密碼,那麼GroupName組中列出並且密碼檔案中有條目的任何人都將被允許進入。

還有另一種方法可以讓多個使用者不那麼具體。可以使用以下指令,而不是建立組檔案:

Require valid-user

使用它而不是Require使用者rbowen行將允許密碼檔案中列出的任何人以及正確輸入密碼的人。

4. 可能的問題

由於指定了基本身份驗證的方式,因此每次從伺服器請求文件時都必須驗證使用者名和密碼。即使您正在重新載入同一頁面以及頁面上的每個影象(如果它們來自受保護的目錄),這也是如此。可以想象,這會減慢一些事情。減慢速度的因素與密碼檔案的大小成正比,因為它必須開啟該檔案,然後沿使用者列表向下,直到找到名字。每次載入頁面時都必須這樣做。

這樣做的結果是,可以在一個密碼檔案中放入多少使用者存在實際限制。此限制將根據您的特定伺服器計算機的效能而有所不同,但是一旦超過幾百個條目,速度可能會有一定下降,並且可能希望在此時考慮不同的身份驗證方法。

5. 替代密碼儲存

由於在純文字檔案中儲存密碼存在上述問題,因此可能希望將密碼儲存在其他位置,例如資料庫中。

mod_authn_dbmmod_authn_dbd是使這成為可能的兩個模組。可以選擇dbmdbd作為儲存格式,而不是選擇AuthBasicProvider檔案。

要選擇dbm檔案而不是文字檔案,例如:

<Directory "/www/docs/private">
    AuthName "Private"
    AuthType Basic
    AuthBasicProvider dbm
    AuthDBMUserFile "/www/passwords/passwd.dbm"
    Require valid-user
</Directory>

6. 使用多個供應者

通過引入基於新提供程式的身份驗證和授權體系結構,您不再需要鎖定到單個身份驗證或授權方法。實際上,可以混合和匹配任意數量的提供者,以便為您提供滿足您需求的方案。在以下範例中,使用基於檔案和LDAP的身份驗證提供程式。

<Directory "/www/docs/private">
    AuthName "Private"
    AuthType Basic
    AuthBasicProvider file ldap
    AuthUserFile "/usr/local/apache/passwd/passwords"
    AuthLDAPURL ldap://ldaphost/o=yourorg
    Require valid-user
</Directory>

在此範例中,檔案提供程式將首先嘗試對使用者進行身份驗證。如果無法對使用者進行身份驗證,則將呼叫LDAP提供程式。如果您的組織實現了多種型別的身份驗證儲存,則可以擴充套件身份驗證範圍。其他認證和授權方案可以包括將一種型別的認證與不同型別的授權混合。例如,針對密碼檔案進行身份驗證,然後針對LDAP目錄進行授權。

正如可以實現多個身份驗證提供程式一樣,也可以使用多種授權方法。在此範例中,正在使用檔案組授權和LDAP組授權。

<Directory "/www/docs/private">
    AuthName "Private"
    AuthType Basic
    AuthBasicProvider file
    AuthUserFile "/usr/local/apache/passwd/passwords"
    AuthLDAPURL ldap://ldaphost/o=yourorg
    AuthGroupFile "/usr/local/apache/passwd/groups"
    Require group GroupName
    Require ldap-group cn=mygroup,o=yourorg
</Directory>

為了進一步授權,授權容器指令(例如<RequireAll><RequireAny>)允許應用邏輯,以便可以通過組態完全控制處理授權的順序。

7. 超越授權

現在,可以應用授權的方式比僅針對單個資料儲存的單個檢查更靈活。現在可以使用順序,邏輯和選擇授權方式。

應用邏輯和排序

控制授權的應用方式和順序過去一直是個謎。在Apache 2.2中,引入了基於提供程式的身份驗證機制,以將實際身份驗證過程與授權和支援功能分離。其中一個好處是可以按特定順序組態和呼叫身份驗證提供程式,而不依賴於auth模組本身的載入順序。同樣基於提供者的機制也已被提交給授權。這意味著Require指令不僅指定應該使用哪些授權方法,還指定呼叫它們的順序。多個授權方法的呼叫順序與Require指令在組態中出現的順序相同。

通過引入授權容器指令(例如<RequireAll><RequireAny>),組態還可以控制何時呼叫授權方法以及何時標準確定何時授予存取許可權。有關如何使用它們表示複雜授權邏輯的範例,請參閱授權容器。

預設情況下,所有Require指令的處理都像包含在<RequireAny>容器指令中一樣。換句話說,如果任何指定的授權方法成功,則授予授權。

使用授權提供程式進行存取控制

使用者名和密碼驗證只是故事的一部分。通常你想讓人們存取基於他們授權以外的東西。

授權提供程式all,env,host和ip用於根據其他基於主機的條件允許或拒絕存取,例如請求文件的計算機的主機名或IP地址。

這些提供程式的用法通過Require指令指定。該指令註冊將在請求處理的授權階段呼叫的授權提供程式。例如:

Require ip address

其中address是IP地址(或部分IP地址)或:

Require host domain_name

其中domain_name是完全限定的域名(或部分域名); 如果需要,可以提供多個地址或域名。
例如,如果有人向留言板傳送垃圾郵件,並且你希望將其保留,則可以執行以下操作:

<RequireAll>
    Require all granted
    Require not ip 10.252.46.165
</RequireAll>

來自該地址的訪客將無法看到該指令涵蓋的內容。相反,如果您擁有機器名稱而不是IP地址,則可以使用它。

<RequireAll>
    Require all granted
    Require not host host.example.com
</RequireAll>

而且,如果您想阻止整個域的存取,只能指定地址或域名的一部分:

<RequireAll>
    Require all granted
    Require not ip 192.168.205
    Require not host phishers.example.com moreidiots.example
    Require not host ke
</RequireAll>