### httpd,Apache的HTTP服務器
Apache的HTTP服務器是一個Subversion可以利用的“重型”網絡服務器,通過一個自定義模塊,**httpd**可以讓Subversion版本庫通過WebDAV/DeltaV協議在客戶端前可見,WebDAV/DeltaV協議是HTTP 1.1的擴展(見`http://www.webdav.org/`來查看詳細信息)。這個協議利用了無處不在的HTTP協議是廣域網的核心這一點,添加了寫能力―更明確一點,版本化的寫―能力。結果就是這樣一個標準化的健壯的系統,作為Apache 2.0軟件的一部分打包,被許多操作系統和第三方產品支持,網絡管理員也不需要打開另一個自定義端口。 這樣一個Apache-Subversion服務器具備了許多**svnserve**沒有的特性,但是也有一點難于配置,靈活通常會帶來復雜性。
下面的討論包括了對Apache配置指示的引用,給了一些使用這些指示的例子,詳細地描述不在本章的范圍之內,Apache小組維護了完美的文檔,公開存放在他們的站點`http://httpd.apache.org`。例如,一個一般的配置參考位于`http://httpd.apache.org/docs-2.0/mod/directives.html`。
同樣,當你修改你的Apache設置,很有可能會出現一些錯誤,如果你還不熟悉Apache的日志子系統,你一定需要認識到這一點。在你的文件`httpd.conf`里會指定Apache生成的訪問和錯誤日志(`CustomLog`和`ErrorLog`指示)的磁盤位置。Subversion的mod_dav_svn使用Apache的錯誤日志接口,你可以瀏覽這個文件的內容查看信息來查找難于發現的問題根源。
**為什么是Apache 2?**
如果你系統管理員,很有可能是你已經運行了Apache服務器,并且有一些高級經驗。寫本文的時候,Apache 1.3是Apache最流行的版本,這個世界因為許多原因而放緩升級到2.X系列:如人們害怕改變,特別是像web服務器這種重要的變化,有些人需要一些在Apache 1.3 API下工作的插件模塊,在等待2.X的版本。無論什么原因,許多人會在首次發現Subversion的Apache模塊只是為Apache 2 API寫的后開始擔心。
對此問題的適當反應是:不需要擔心,同時運行Apache 1.3和Apache 2非常簡單,只需要安裝到不同的位置,用Apache 2作為Subversion的專用服務器,并且不使用80端口,客戶端可以訪問版本庫時在URL里指定端口:
~~~
$ svn checkout http://host.example.com:7382/repos/project
…
~~~
### 必備條件
為了讓你的版本庫使用HTTP網絡,你基本上需要兩個包里的四個部分。你需要Apache **httpd** 2.0和包括的**mod_dav** DAV模塊,Subversion和與之一同分發的**mod_dav_svn**文件系統提供者模塊,如果你有了這些組件,網絡化你的版本庫將非常簡單,如:
-
配置好httpd 2.0,并且使用mod_dav啟動,
-
為mod_dav安裝mod_dav_svn插件,它會使用Subversion的庫訪問版本庫,并且
-
配置你的`httpd.conf`來輸出(或者說暴露)版本庫。
你可以通過從源代碼編譯**httpd**和Subversion來完成前兩個項目,也可以通過你的系統上的已經編譯好的二進制包來安裝。最新的使用Apache HTTP的Subversion的編譯方法和Apache的配置方式可以看Subversion源代碼樹根目錄的`INSTALL`文件。
### 基本的Apache配置
一旦你安裝了必須的組件,剩下的工作就是在`httpd.conf`里配置Apache,使用`LoadModule`來加載mod_dav_svn模塊,這個指示必須先與其它Subversion相關的其它配置出現,如果你的Apache使用缺省布局安裝,你的**mod_dav_svn**模塊一定在Apache安裝目錄(通常是在`/usr/local/apache2`)的`modules`子目錄,`LoadModule`指示的語法很簡單,影射一個名字到它的共享庫的物理位置:
~~~
LoadModule dav_svn_module modules/mod_dav_svn.so
~~~
注意,如果**mod_dav**是作為共享對象編譯(而不是靜態鏈接到**httpd**程序),你需要為它使用使用`LoadModule`語句,一定確定它在**mod_dav_svn**之前:
~~~
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
~~~
在你的配置文件后面的位置,你需要告訴Apache你在什么地方保存Subversion版本庫(也許是多個),`位置`指示有一個很像XML的符號,開始于一個開始標簽,以一個結束標簽結束,配合中間許多的其它配置。`Location`指示的目的是告訴Apache在特定的URL以及子URL下需要特殊的處理,如果是為Subversion準備的,你希望可以通過告訴Apache特定URL是指向版本化的資源,從而把支持轉交給DAV層,你可以告訴Apache將所有路徑部分(URL中服務器名稱和端口之后的部分)以`/repos/`開頭的URL交由DAV服務提供者處理。一個DAV服務提供者的版本庫位于`/absolute/path/to/repository`,可以使用如下的`httpd.conf`語法:
~~~
<Location /repos>
DAV svn
SVNPath /absolute/path/to/repository
</Location>
~~~
如果你計劃支持多個具備相同父目錄的Subversion版本庫,你有另外的選擇,`SVNParentPath`指示,來表示共同的父目錄。舉個例子,如果你知道你會在`/usr/local/svn`下創建多個Subversion版本庫,并且通過類似`http://my.server.com/svn/repos1`,`http://my.server.com/svn/repos2`的URL訪問,你可以用后面例子中的`httpd.conf`配置語法:
~~~
<Location /svn>
DAV svn
# any "/svn/foo" URL will map to a repository /usr/local/svn/foo
SVNParentPath /usr/local/svn
</Location>
~~~
使用上面的語法,Apache會代理所有URL路徑部分為`/svn/`的請求到Subversion的DAV提供者,Subversion會認為`SVNParentPath`指定的目錄下的所有項目是真實的Subversion版本庫,這通常是一個便利的語法,不像是用`SVNPath`指示,我們在此不必為創建新的版本庫而重啟Apache。
請確定當你定義新的`位置`,不會與其它輸出的位置重疊,例如你的主要`DocumentRoot`是`/www`,不要把Subversion版本庫輸出到`<Location /www/repos>`,如果一個請求的URI是`/www/repos/foo.c`,Apache不知道是直接到`repos/foo.c`訪問這個文件還是讓**mod_dav_svn**代理從Subversion版本庫返回`foo.c`。
**服務器名稱和拷貝請求**
Subversion利用`COPY`請求類型來執行服務器端的文件和目錄拷貝,作為一個健全的Apache模塊的一部分,拷貝源和拷貝的目標通常坐落在同一個機器上,為了滿足這個需求,你或許需要告訴mod_dav服務器主機的名稱,通常你可以使用`httpd.conf`的`ServerName`指示來完成此目的。
~~~
ServerName svn.example.com
~~~
如果你通過`NameVirtualHost`指示使用Apache的虛擬主機,你或許需要`ServerAlias`指示來指定額外的名稱,再說一次,可以查看Apache文檔的來得到更多細節。
在本階段,你一定要考慮訪問權限問題,如果你已經作為普通的web服務器運行過Apache,你一定有了一些內容―網頁、腳本和其他。這些項目已經配置了許多在Apache下可以工作的訪問許可,或者更準確一點,允許Apache與這些文件一起工作。Apache當作為Subversion服務器運行時,同樣需要正確的訪問許可來讀寫你的Subversion版本庫。(見[服務器和訪問許可:一個警告]( "服務器和訪問許可:一個警告")。)
你會需要檢驗權限系統的設置滿足Subversion的需求,同時不會把以前的頁面和腳本搞亂。這或許意味著修改Subversion的訪問許可來配合Apache服務器已經使用的工具,或者可能意味著需要使用`httpd.conf`的`User`和`Group`指示來指定Apache作為運行的用戶和Subversion版本庫的組。并不是只有一條正確的方式來設置許可,每個管理員都有不同的原因來以特定的方式操作,只需要意識到許可關聯的問題經常在為Apache配置Subversion版本庫的過程中被疏忽。
### 認證選項
此時,如果你配置的`httpd.conf`保存如下的內容
~~~
<Location /svn>
DAV svn
SVNParentPath /usr/local/svn
</Location>
~~~
這樣你的版本庫對全世界是可以“匿名”訪問的,直到你配置了一些認證授權政策,你通過`Location`指示來使Subversion版本庫可以被任何人訪問,換句話說,
-
任何人可以使用Subversion客戶端來從版本庫URL取出一個工作拷貝(或者是它的子目錄),
-
任何人可以在瀏覽器輸入版本庫URL交互瀏覽的方式來查看版本庫的最新修訂版本,并且
-
任何人可以提交到版本庫。
#### 基本HTTP認證
最簡單的客戶端認證方式是通過HTTP基本認證機制,簡單的使用用戶名和密碼來驗證一個用戶所自稱的身份,Apache提供了一個**htpasswd**工具來管理可接受的用戶名和密碼,這些就是你希望賦予Subversion特別權限的用戶,讓我們給Sally和Harry賦予提交權限,首先,我們需要添加他們到密碼文件。
~~~
$ ### First time: use -c to create the file
$ ### Use -m to use MD5 encryption of the password, which is more secure
$ htpasswd -cm /etc/svn-auth-file harry
New password: *****
Re-type new password: *****
Adding password for user harry
$ htpasswd -m /etc/svn-auth-file sally
New password: *******
Re-type new password: *******
Adding password for user sally
$
~~~
下一步,你需要在`httpd.conf`的`Location`區里添加一些指示來告訴Apache如何來使用這些密碼文件,`AuthType`指示指定系統使用的認證類型,這種情況下,我們需要指定`Basic`認證系統,`AuthName`是你提供給認證域一個任意名稱,大多數瀏覽器會在向用戶詢問名稱和密碼的彈出窗口里顯示這個名稱,最終,使用`AuthUserFile`指示來指定使用**htpasswd**創建的密碼文件的位置。
添加完這三個指示,你的`<Location>`區塊一定像這個樣子:
~~~
<Location /svn>
DAV svn
SVNParentPath /usr/local/svn
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /etc/svn-auth-file
</Location>
~~~
這個`<Location>`區塊還沒有結束,還不能做任何有用的事情,它只是告訴Apache當需要授權時,要去向Subversion客戶端索要用戶名和密碼。我們這里遺漏的,是一些告訴Apache*什么樣*客戶端需要授權的指示。哪里需要授權,Apache就會在哪里要求認證,最簡單的方式是保護所有的請求,添加`Require valid-user`來告訴Apache任何請求需要認證的用戶:
~~~
<Location /svn>
DAV svn
SVNParentPath /usr/local/svn
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /etc/svn-auth-file
Require valid-user
</Location>
~~~
一定要閱讀后面的部分([“授權選項”一節]( "授權選項"))來得到`Require`的細節,和授權政策的其他設置方法。
需要警惕:HTTP基本認證的密碼是用明文傳輸,因此非常不可靠的,如果你擔心密碼偷窺,最好是使用某種SSL加密,所以客戶端認證使用`https://`而不是`http://`,為了方便,你可以配置Apache為自簽名認證。 [[23](#)] 參考Apache的文檔(和OpenSSL文檔)來查看怎樣做。
#### SSL證書管理
商業應用需要越過公司防火墻的版本庫訪問,防火墻需要小心的考慮非認證用戶“吸取”他們的網絡流量的情況,SSL讓那種形式的關注更不容易導致敏感數據泄露。
如果Subversion使用OpenSSL編譯,它就會具備與Subversion服務器使用`https://`的URL通訊的能力,Subversion客戶端使用的Neon庫不僅僅可以用來驗證服務器證書,也可以必要時提供客戶端證書,如果客戶端和服務器交換了SSL證書并且成功地互相認證,所有剩下的交流都會通過一個會話關鍵字加密。
怎樣產生客戶端和服務器端證書以及怎樣使用它們已經超出了本書的范圍,許多書籍,包括Apache自己的文檔,描述這個任務,現在我們*可以*覆蓋的是普通的客戶端怎樣來管理服務器與客戶端證書。
當通過`https://`與Apache通訊時,一個Subversion客戶端可以接收兩種類型的信息:
-
一個服務器證書
-
一個客戶端證書的要求
如果客戶端接收了一個服務器證書,它需要去驗證它是可以相信的:這個服務器是它自稱的那一個嗎?OpenSSL庫會去檢驗服務器證書的簽名人或者是*核證機構*(CA)。如果OpenSSL不可以自動信任這個CA,或者是一些其他的問題(如證書過期或者是主機名不匹配),Subversion命令行客戶端會詢問你是否愿意仍然信任這個證書:
~~~
$ svn list https://host.example.com/repos/project
Error validating server certificate for 'https://host.example.com:443':
- The certificate is not issued by a trusted authority. Use the
fingerprint to validate the certificate manually!
Certificate information:
- Hostname: host.example.com
- Valid: from Jan 30 19:23:56 2004 GMT until Jan 30 19:23:56 2006 GMT
- Issuer: CA, example.com, Sometown, California, US
- Fingerprint: 7d:e1:a9:34:33:39:ba:6a:e9:a5:c4:22:98:7b:76:5c:92:a0:9c:7b
(R)eject, accept (t)emporarily or accept (p)ermanently
~~~
這個對話看起來很熟悉,這是你會在web瀏覽器(另一種HTTP客戶端,就像Subversion)經常看到的問題,如果你選擇(p)ermanent選項,服務器證書會存放在你存放那個用戶名和密碼緩存(見[“客戶端憑證緩存”一節]("客戶端憑證緩存")。)的私有運行區`auth/`中,緩存后,Subversion會自動記住在以后的交流中信任這個證書。
你的運行中`servers`文件也會給你能力可以讓Subversion客戶端自動信任特定的CA,包括全局的或是每主機為基礎的,只需要設置`ssl-authority-files`為一組逗號隔開的PEM加密的CA證書列表:
~~~
[global]
ssl-authority-files = /path/to/CAcert1.pem;/path/to/CAcert2.pem
~~~
許多OpenSSL安裝包括一些預先定義好的可以普遍信任的“缺省的”CA,為了讓Subversion客戶端自動信任這些標準權威,設置`ssl-trust-default-ca`為`true`。
當與Apache通話時,Subversion客戶端也會收到一個證書的要求,Apache是詢問客戶端來證明自己的身份:這個客戶端是否是他所說的那一個?如果一切正常,Subversion客戶端會發送回一個通過Apache信任的CA簽名的私有證書,一個客戶端證書通常會以加密方式存放在磁盤,使用本地密碼保護,當Subversion收到這個要求,它會詢問你證書的路徑和保護用的密碼:
~~~
$ svn list https://host.example.com/repos/project
Authentication realm: https://host.example.com:443
Client certificate filename: /path/to/my/cert.p12
Passphrase for '/path/to/my/cert.p12': ********
…
~~~
注意這個客戶端證書是一個“p12”文件,為了讓Subversion使用客戶端證書,它必須是運輸標準的PKCS#12格式,大多數瀏覽器可以導入和導出這種格式的證書,另一個選擇是用OpenSSL命令行工具來轉化存在的證書為PKCS#12格式。
再次,運行中`servers`文件允許你為每個主機自動響應這種要求,單個或兩條信息可以用運行參數來描述:
~~~
[groups]
examplehost = host.example.com
[examplehost]
ssl-client-cert-file = /path/to/my/cert.p12
ssl-client-cert-password = somepassword
~~~
一旦你設置了`ssl-client-cert-file`和 `ssl-client-cert-password`參數,Subversion客戶端可以自動響應客戶端證書請求而不會打擾你。
### 授權選項
此刻,你已經配置了認證,但是沒有配置授權,Apache可以要求用戶認證并且確定身份,但是并沒有說明這個身份的怎樣允許和限制,這個部分描述了兩種控制訪問版本庫的策略。
#### 整體訪問控制
最簡單的訪問控制形式是授權特定用戶為只讀版本庫訪問或者是讀/寫訪問版本庫。
你可以通過在`<Location>`區塊添加`Require valid-user`指示來限制所有的版本庫操作,使用我們前面的例子,這意味著只有客戶端只可以是`harry`或者`sally`,而且他們必須提供正確的用戶名及對應密碼,這樣允許對Subversion版本庫做任何事:
~~~
<Location /svn>
DAV svn
SVNParentPath /usr/local/svn
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
# only authenticated users may access the repository
Require valid-user
</Location>
~~~
有時候,你不需要這樣嚴密,舉個例子,Subversion自己在`http://svn.collab.net/repos/svn`的源代碼允許全世界的人執行版本庫的只讀操作(例如檢出我們的工作拷貝和使用瀏覽器瀏覽版本庫),但是限定只有認證用戶可以執行寫操作。為了執行特定的限制,你可以使用`Limit`和`LimitExcept`配置指示,就像`Location`指示,這個區塊有開始和結束標簽,你需要在`<Location>`中添加這個指示。
在`Limit`和`LimitExcept`中使用的參數是可以被這個區塊影響的HTTP請求類型,舉個例子,如果你希望禁止所有的版本庫訪問,只是保留當前支持的只讀操作,你可以使用`LimitExcept`指示,并且使用`GET`,`PROPFIND`,`OPTIONS`和`REPORT`請求類型參數,然后前面提到過的`Require valid-user`指示將會在`<LimitExcept>`區塊中而不是在`<Location>`區塊。
~~~
<Location /svn>
DAV svn
SVNParentPath /usr/local/svn
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
# For any operations other than these, require an authenticated user.
<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
</LimitExcept>
</Location>
~~~
這里只是一些簡單的例子,想看關于Apache訪問控制`Require`指示的更深入信息,可以查看Apache文檔中的教程集`http://httpd.apache.org/docs-2.0/misc/tutorials.html`中的`Security`部分。
#### 每目錄訪問控制
也可以使用Apache的httpd模塊**mod_authz_svn**更加細致的設置訪問權限,這個模塊收集客戶端傳遞過來的不同的晦澀的URL信息,詢問**mod_dav_svn**來解碼,然后根據在配置文件定義的訪問政策來裁決請求。
如果你從源代碼創建Subversion,**mod_authz_svn**會自動附加到**mod_dav_svn**,許多二進制分發版本也會自動安裝,為了驗證它是安裝正確,確定它是在`httpd.conf`的`LoadModule`指示中的**mod_dav_svn**后面:
~~~
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
~~~
為了激活這個模塊,你需要配置你的`Location`區塊的`AuthzSVNAccessFile`指示,指定保存路徑中的版本庫訪問政策的文件。(一會兒我們將會討論這個文件的格式。)
Apache非常的靈活,你可以從三種模式里選擇一種來配置你的區塊,作為開始,你選擇一種基本的配置模式。(下面的例子非常簡單;見Apache自己的文檔中的認證和授權選項來查看更多的細節。)
最簡單的區塊是允許任何人可以訪問,在這個場景里,Apache決不會發送認證請求,所有的用戶作為“匿名”對待。
**例6.1.匿名訪問的配置實例。**
~~~
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
# our access control policy
AuthzSVNAccessFile /path/to/access/file
</Location>
~~~
在另一個極端,你可以配置為拒絕所有人的認證,所有客戶端必須提供證明自己身份的證書,你通過`Require valid-user`指示來阻止無條件的認證,并且定義一種認證的手段。
**例6.2.一個認證訪問的配置實例。**
~~~
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
# our access control policy
AuthzSVNAccessFile /path/to/access/file
# only authenticated users may access the repository
Require valid-user
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
</Location>
~~~
第三種流行的模式是允許認證和匿名用戶的組合,舉個例子,許多管理員希望允許匿名用戶讀取特定的版本庫路徑,但希望只有認證用戶可以讀(或者寫)更多敏感的區域,在這個設置里,所有的用戶開始時用匿名用戶訪問版本庫,如果你的訪問控制策略在任何時候要求一個真實的用戶名,Apache將會要求認證客戶端,為此,你可以同時使用`Satisfy Any`和`Require valid-user`指示。
**例6.3.一個混合認證/匿名訪問的配置實例。**
~~~
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
# our access control policy
AuthzSVNAccessFile /path/to/access/file
# try anonymous access first, resort to real
# authentication if necessary.
Satisfy Any
Require valid-user
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
</Location>
~~~
一旦你的基本`Location`區塊已經配置了,你可以創建一個定義一些授權規則的訪問文件。
訪問文件的語法與**svnserve.conf**和運行中配置文件非常相似,以(`#`)開頭的行會被忽略,在它的簡單形式里,每一小節命名一個版本庫和一個里面的路徑,認證用戶名是在每個小節中的選項名,每個選項的值描述了用戶訪問版本庫的級別:`r`(只讀)或者`rw`(讀寫),如果用戶沒有提到,訪問是不允許的。
具體一點:這個小節的名稱是`[repos-name:path]`或者`[path]`的形式,如果你使用`SVNParentPath`指示,指定版本庫的名字是很重要的,如果你漏掉了他們,`[/some/dir]`部分就會與`/some/dir`的所有版本庫匹配,如果你使用`SVNPath`指示,因此在你的小節中只是定義路徑也很好―畢竟只有一個版本庫。
~~~
[calc:/branches/calc/bug-142]
harry = rw
sally = r
~~~
在第一個例子里,用戶`harry`對`calc`版本庫中`/branches/calc/bug-142`具備完全的讀寫權利,但是用戶`sally`只有讀權利,任何其他用戶禁止訪問這個目錄。
當然,訪問控制是父目錄傳遞給子目錄的,這意味著我們可以為Sally指定一個子目錄的不同訪問策略:
~~~
[calc:/branches/calc/bug-142]
harry = rw
sally = r
# give sally write access only to the 'testing' subdir
[calc:/branches/calc/bug-142/testing]
sally = rw
~~~
現在Sally可以讀取分支的`testing`子目錄,但對其他部分還是只可以讀,同時,Harry對整個分支還繼續有完全的讀寫權限。
也可以通過繼承規則明確的的拒絕某人的訪問,只需要設置用戶名參數為空:
~~~
[calc:/branches/calc/bug-142]
harry = rw
sally = r
[calc:/branches/calc/bug-142/secret]
harry =
~~~
在這個例子里,Harry對`bug-142`目錄樹有完全的讀寫權限,但是對`secret`子目錄沒有任何訪問權利。
有一件事需要記住的是需要找到最匹配的目錄,**mod_authz_svn**模塊首先找到匹配自己的目錄,然后父目錄,然后父目錄的父目錄,就這樣繼續下去,更具體的路徑控制會覆蓋所有繼承下來的訪問控制。
缺省情況下,沒有人對版本庫有任何訪問,這意味著如果你已經從一個空文件開始,你會希望給所有用戶對版本庫根目錄具備讀權限,你可以使用`*`實現,用來代表“所有用戶”:
~~~
[/]
* = r
~~~
這是一個普通的設置;注意在小節名中沒有提到版本庫名稱,這讓所有版本庫對所有的用戶可讀,不管你是使用`SVNPath`或是`SVNParentPath`。當所有用戶對版本庫有了讀權利,你可以賦予特定用戶對特定子目錄的`rw`權限。
星號(`*`)參數需要在這里詳細強調:這是匹配匿名用戶的*唯一*模式,如果你已經配置了你的`Location`區塊允許匿名和認證用戶的混合訪問,所有用戶作為Apache匿名用戶開始訪問,**mod_authz_svn**會在要訪問路徑的定義中查找`*`值;如果找不到,Apache就會要求真實的客戶端認證。
訪問文件也允許你定義一組的用戶,很像Unix的`/etc/group`文件:
~~~
[groups]
calc-developers = harry, sally, joe
paint-developers = frank, sally, jane
everyone = harry, sally, joe, frank, sally, jane
~~~
組可以被賦予通用戶一樣的訪問權限,使用“at”(`@`)前綴來加以區別:
~~~
[calc:/projects/calc]
@calc-developers = rw
[paint:/projects/paint]
@paint-developers = rw
jane = r
~~~
...并且非常接近。
#### 關閉路徑為基礎的檢查
**mod_dav_svn**模塊做了許多工作來確定你標記為“不可讀”的數據不會因意外而泄露,這意味著需要緊密監控通過**svn checkout**或是**svn update**返回的路徑和文件內容,如果這些命令遇到一些根據認證策略不是可讀的路徑,這個路徑通常會被一起忽略,在歷史或者重命名操作時―例如運行一個類似**svn cat -r OLD foo.c**的命令來操作一個很久以前改過名字的文件 ― 如果一個對象的以前的名字檢測到是只讀的,重命令追蹤就會終止。
所有的路徑檢查在有時會非常昂貴,特別是**svn log**的情況。當檢索一列修訂版本時,服務器會查看所有修訂版本修改的路徑,并且檢查可讀性,如果發現了一個不可讀路徑,它會從修訂版本的修改路徑中忽略(可以查看`--verbose`選項),并且整個的日志信息會被禁止,不必多說,這種影響大量文件修訂版本的操作會非常耗時。這是安全的代價:即使你并沒有配置**mod_authz_svn**模塊,**mod_dav_svn**還是會詢問**httpd**來對所有路徑運行認證檢查,**mod_dav_svn**模塊沒有辦法知道那個認證模塊被安裝,所以只有詢問Apache來調用所提供的模塊。
在另一方面,也有一個安全艙門允許你用安全特性來交換速度,如果你不是堅持要求有每目錄授權(如不使用 **mod_authz_svn**和類似的模塊),你就可以關閉所有的路徑檢查,在你的`httpd.conf`文件,使用`SVNPathAuthz`指示:
**例6.4.關閉所有的路經檢查**
~~~
<Location /repos>
DAV svn
SVNParentPath /usr/local/svn
SVNPathAuthz off
</Location>
~~~
`SVNPathAuthz`指示缺省是打開的,當設置為“off”時,所有的路徑為基礎的授權都會關閉;**mod_dav_svn**停止對每個目錄調用授權檢查。
### 額外的糖果
我們已經覆蓋了關于認證和授權的Apache和mod_dav_svn的大多數選項,但是Apache還提供了許多很好的特性。
#### 版本庫瀏覽
一個非常有用的好處是使用Apache/WebDAV配置Subversion版本庫時可以用普通的瀏覽器察看最新的版本庫文件,因為Subversion使用URL來鑒別版本庫版本化的資源,版本庫使用的HTTP為基礎的URL也可以直接輸入到Web瀏覽器中,你的瀏覽器會發送一個`GET`請求到URL,根據訪問的URL是指向一個版本化的目錄還是文件,mod_dav_svn會負責列出目錄列表或者是文件內容。
因為URL不能確定你所希望看到的資源的版本,mod_dav_svn會一直返回最新的版本,這樣會有一些美妙的副作用,你可以直接把Subversion的URL傳遞給文檔作為引用,這些URL會一直指向文檔最新的材料,當然,你也可以在別的網站作為超鏈使用這些URL。
你通常會在版本化的文件的URL之外得到更多地用處―畢竟那里是有趣的內容存在的地方,但是你會偶爾瀏覽一個Subversion的目錄列表,你會很快發現展示列表生成的HTML非常基本,并且一定沒有在外觀上(或者是有趣上)下功夫,為了自定義這些目錄顯示,Subversion提供了一個XML目錄特性,一個單獨的`SVNIndexXSLT`指示在你的`httpd.conf`文件版本庫的`Location`塊里,它將會指導mod_dav_svn在顯示目錄列表的時候生成XML輸出,并且引用你選擇的XSLT樣式表文件:
~~~
<Location /svn>
DAV svn
SVNParentPath /usr/local/svn
SVNIndexXSLT "/svnindex.xsl"
…
</Location>
~~~
使用`SVNIndexXSLT`指示和創建一個XSLT樣式表,你可以讓你的目錄列表的顏色模式與你的網站的其它部分匹配,否則,如果你愿意,你可以使用Subversion源分發版本中的`tools/xslt/`目錄下的樣例樣式表。記住提供給`SVNIndexXSLT` 指示的路徑是一個URL路徑―瀏覽器需要閱讀你的樣式表來利用它們!
**我可以看到老的修訂版本嗎?**
通過一個普通的瀏覽器?一句話:不可以,至少是當你只使用**mod_dav_svn**作為唯一的工具時。
你的Web瀏覽器只會說普通的HTTP,也就是說它只會GET公共的URL,這個URL代表了最新版本的文件和目錄,根據WebDAV/DeltaV規范,每種服務器定義了一種私有的URL語法來代表老的資源的版本,這個語法對客戶端是不透明的,為了得到老的版本,一個客戶端必須通過一種規范過程來“發現”正確的URL;這個過程包括執行一系列WebDAV PROPFIND請求和理解DeltaV概念,這些事情一般是你的web瀏覽器做不了的。
為了回答這些問題,一個明顯的看老版本文件和目錄的方式是帶`--revision`參數的**svn list**和**svn cat**命令,為了在瀏覽器里察看老版本,你可以使用第三方的軟件,一個好的例子是ViewCVS(`http://viewcvs.sourceforge.net/`),ViewCVS最初寫出來是為了在web顯示CVS版本庫,最新的帶血的(此時正在編寫)版本也已經可以理解Subversion版本庫了。
#### 其它特性
Apache作為一個健壯的Web服務器的許多特性也可以用來增加Subversion的功能性和安全性,Subversion使用Neon與Apache通訊,這是一種一般的HTTP/WebDAV庫,可以支持SSL和Deflate壓縮(是**gzip**和**PKZIP**程序用來“壓縮”文件為數據塊的一樣的算法)之類的機制。你只需要編譯你希望Subversion和Apache需要的特性,并且正確的配置程序來使用這些特性。
Deflate壓縮給服務器和客戶端帶來了更多地負擔,壓縮和解壓縮減少了網絡傳輸的實際文件的大小,如果網絡帶寬比較緊缺,這種方法會大大提高服務器和客戶端之間發送數據的速度,在極端情況下,這種最小化的傳輸會造成超時和成功的區別。
不怎么有趣,但同樣重要,是Apache和Subversion關系的一些特性,像可以指定自定義的端口(而不是缺省的HTTP的80)或者是一個Subversion可以被訪問的虛擬主機名,或者是通過代理服務器訪問的能力,這些特性都是Neon所支持的,所以Subversion輕易得到這些支持。
最后,因為**mod_dav_svn**是使用一個半完成的WebDAV/DeltaV方言,所以通過第三方的DAV客戶端訪問也是可能的,幾乎所有的現代操作系統(Win32、OS X和Linux)都有把DAV服務器影射為普通的網絡“共享”的內置能力,這是一個復雜的主題;察看[附錄C, *WebDAV和自動版本化*]( "附錄C.WebDAV和自動版本化")來得到更多細節。
他們討厭這樣做。
當使用自簽名的服務器時仍會遭受“中間人”攻擊,但是與偷取未保護的密碼相比,這樣的攻擊比一個偶然的獲取要艱難許多。
更多有安全意識的人不會希望在運行中`servers`文件保存客戶端證書密碼。
- 第1章介紹
- Subversion的歷史
- Subversion的特性
- Subversion的架構
- 安裝Subversion
- Subversion的組件
- 快速入門
- 第2章基本概念
- 版本模型
- Subversion實戰
- 摘要
- 第3章指導教程
- 導入
- 修訂版本: 號碼、關鍵字和日期,噢,我的!
- 初始化的Checkout
- 基本的工作周期
- 檢驗歷史
- 其他有用的命令
- 摘要
- 第4章分支與合并
- 使用分支
- 在分支間拷貝修改
- 常見用例
- 轉換工作拷貝
- 標簽
- 分支維護
- 摘要
- 第5章版本庫管理
- 版本庫的創建和配置
- 版本庫維護
- 添加項目
- 摘要
- 第6章配置服務器
- 網絡模型
- svnserve,一個自定義的服務器
- httpd,Apache的HTTP服務器
- 支持多種版本庫訪問方法
- 第7章高級主題
- 屬性
- Peg和實施修訂版本
- 外部定義
- 賣主分支
- 本地化
- Subversion版本庫URL
- 第8章開發者信息
- 使用API
- 進入工作拷貝的管理區
- WebDAV
- 使用內存池編程
- 為Subversion做貢獻
- 第9章Subversion完全參考
- svn add
- svn blame
- svn cat
- svn checkout
- svn cleanup
- svn commit
- svn copy
- svn delete
- svn diff
- svn export
- svn help
- svn import
- svn info
- svn list
- svn log
- svn merge
- svn mkdir
- svn move
- svn propdel
- svn propedit
- svn propget
- svn proplist
- svn propset
- svn resolved
- svn revert
- svn status
- svn switch
- svn update
- svnadmin
- svnadmin create
- svnadmin deltify
- svnadmin dump
- svnadmin help
- svnadmin hotcopy
- svnadmin list-dblogs
- svnadmin list-unused-dblogs
- svnadmin load
- svnadmin lstxns
- svnadmin recover
- svnadmin rmtxns
- svnadmin setlog
- svnadmin verify
- svnlook
- svnlook author
- svnlook cat
- svnlook changed
- svnlook date
- svnlook diff
- svnlook dirs-changed
- svnlook help
- svnlook history
- svnlook info
- svnlook log
- svnlook propget
- svnlook proplist
- svnlook tree
- svnlook uuid
- svnlook youngest
- svnserve
- svnversion
- mod_dav_svn Configuration Directives
- 附錄A.Subversion對于CVS用戶
- 目錄的版本
- 更多離線操作
- 區分狀態和更新
- 分支和標簽
- 元數據屬性
- 沖突解決
- 二進制文件和轉化
- 版本化的模塊
- 認證
- 轉化CVS版本庫到Subversion
- 附錄C.WebDAV和自動版本化
- 自動版本化交互性
- Subversion和DeltaV
- 術語表