为了使用TortoiseSVN(或任何其他Subversion客户端),你需要放置你的版本库,你可以将版本库存于本地并使用file://协议访问,也可以放置于服务器,使用http://或svn://访问,这两种服务器协议也可以被加密,使用https://或svn+ssh://。本章介绍了在Windows主机上设置一个服务器的步骤。
如果你没有一个服务器,或者你独自工作,本地版本库会是你的最佳选择,你可以跳过本章,直接到第 4 章
版本库。
3.1. 以Apache为基础的服务器
3.1.1. 简介
所有可能的服务器当中,Apache为基础的服务器是最灵活的,尽管配置有一点复杂,但是提供了其他服务器没有的便利:
WebDAV Apache为基础的Subversion服务器使用WebDAV协议,许多其他程序支持这个协议,你可以在Windows资源管理器中将这样的版本库装载为一个“网络文件夹”,就像访问文件系统的其他目录一样访问它。
- 浏览版本库
- 你可以将浏览器指向版本库的URL,无需安装Subversion客户端就可以浏览内容,这样可以扩大访问你数据的用户圈。
- 认证
- 你可以使用所有Apache支持的认证机制,包括SSPI和LDAP。
- 安全
- 因为Apache非常稳定和安全,你的版本库可以自动获得同样的安全性,包括SSL加密。
3.1.2. 安装Apache
无论是Windows2000、WinXP+SP1还是Windows2003,在安装Apache之前需要做的第一件事。
|
警告 |
请注意,Windows XP如果没有安装SP1将会导致不正常的网络传输,从而搞坏你的版本库! |
- 从Apache网站http://httpd.apache.org/download.cgi下载最新版本的Apache,请确定你下载的版本高于2.0.54-1.3.xx的版本不能工作!同样,低于2.0.54的版本不能与Subversion
1.2一起工作,因为Apache低于2.0.54的Windows版本的编译存在问题。
- 一旦你有了Apache2安装程序,你可以双击它,然后它会指导你的安装过程,请确认你输入的server的URL正确(如果你的服务器没有dns名称,请直接输入IP地址)。我建议安装Apache
为所有用户,在80端口,作为一个服务 。注意:如果你已经有了IIS或其他监听80段口的程序,安装会失败,如果发生这种情况,直接到程序的安装目录\Apache
Group\Apache2\conf ,打开httpd.conf 。编辑文件的Listen
80 为其他可用的端口,例如Listen 81 ,然后重新启动-这样就不会那个问题了。
- 现在可以测试Apache服务器了,将浏览器指向
http://localhost/ -将会看到一个预先配置的网站。
|
小心 |
|
如果你决定将Apache安装为服务,缺省情况以本地系统帐户运行会发出警告,更安全的方法是为Apache创建一个单独的运行帐户。
请确认Apache运行的帐户是版本库目录的访问控制列表(右键目录|属性|安全)中一个明确的条目,对目录有完全的控制能力,否则,用户不能提交他们的修改。
即使Apache运行于本地系统,你仍然需要这个条目(这种情况下将是SYSTEM帐户)。
如果没有设置Apache的访问权限,你的用户会得到“拒绝访问(Access denied)”的错误信息,在Apache的错误日志中为错误500。
3.1.3. 安装Subversion
- 从http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91下载最新版本的Subversion。
- 运行Subversion安装程序,并根据指导安装,如果Subversion认识到你安装了Apache,你就几乎完成了工作,如果它没有找到Apache服务器,你还有额外的步骤。
- 使用Windwos资源管理器,来到Subversion的安装目录(通常是
c:\program
files\Subversion ),找到文件/httpd/mod_dav_svn.so 和mod_authz_svn.so ,拷贝这些文件到Apache的模块目录(通常是c:\program
files\apache group\apache2\modules )。
- 从Subversion安装目录将
/bin/libdb43.dll 拷贝到Apache的模块目录。
- 使用记事本之类的文本编辑器修改Apache的配置文件(通常是
C:\Program
Files\Apache Group\Apache2\conf\httpd.conf ),做出如下修改:
去掉如下几行的注释(删除 '# '标记):
#LoadModule dav_fs_module modules/mod_dav_fs.so
#LoadModule dav_module modules/mod_dav.so
将下面几行添加到LoadModule 部分的最后。
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
3.1.4. 配置
现在你已经设置了Apache和Subversion,但是Apache不知道如何处理Subversion客户端,例如TortoiseSVN。为了让Apache知道哪个目录是用来作为Subversion版本库,你需要使用编辑器(例如记事本)编辑Apache的配置文件(通常是c:\program
files\apache group\apache2\conf\httpd.conf ):
- 在配置文件最后添加如下几行:
<Location /svn> DAV svn SVNListParentPath
on SVNParentPath D:\SVN AuthType Basic AuthName
"Subversion repositories" AuthUserFile
passwd #AuthzSVNAccessFile svnaccessfile Require
valid-user </Location>
这个配置告诉Apache你的所有的Subversion版本库在物理上位于D:\SVN ,版本库对外的URL是:
http://MyServer/svn/ ,访问需要文件passwd 中的用户/密码限制。
- 为了创建
passwd 文件,再次打开命令行提示符(DOS),来到apache2目录(通常是c:\program
files\apache group\apache2 )通过输入下面的命令创建文件
bin\htpasswd -c passwd <username>
This will create a file with the name passwd which
is used for authentication. Additional users can
be added with
bin\htpasswd passwd <username>
- 再次重启Apache服务。
- 将浏览器指向
http://MyServer/svn/MyNewRepository (MyNewRepository 是你此前创建的版本库名),如果一切正常,你会被提示输入用户名和密码,然后你会看到版本库的内容。
你刚才输入的解释是:
表 3.1. 设置Apache的httpd.conf
设置 |
解释 |
<Location /svn> |
意思是Subversion版本库的URL是http://MyServer/svn/ |
DAV svn |
告诉Apache是哪个模块响应那个URL的请求-此刻是Subversion模块。 |
SVNListParentPath on |
对于Subversion1.3或者更高版本,这个指示表示显示所有SVNParentPath下的版本库。 |
SVNParentPath D:\SVN |
告诉Subversion需要查看的版本库位于D:\SVN 之下 |
AuthType Basic |
激活基本认证,就是用户名/密码 |
AuthName "Subversion repositories" |
用来说明何时弹出要求用户输入认证信息的认证对话框 |
AuthUserFile passwd |
指定使用的认证密码文件 |
AuthzSVNAccessFile |
位置Subversion版本库的访问控制文件的路径 |
Require valid-user |
指定只有输入了正确的用户/密码的用户可以访问URL |
但是那只是一个例子,对于Apache你有很多的选择。
- 如果你希望所有人可以读你的版本库,但是只有特定用户可以写,你可以修改下面几行
Require valid-user
to
<LimitExcept GET PROPFIND OPTIONS
REPORT> Require valid-user </LimitExcept>
- 使用
passwd 可以整体的控制对版本库的访问,但是如果你希望精确的控制版本库目录访问,你可以修改需要下面几行
#AuthzSVNAccessFile svnaccessfile
,并且创建Subversion的访问控制文件。Apache将会确保只有有效的用户可以访问你的/svn 目录,然后将用户名传递给Subversion的AuthzSVNAccessFile模块,这样就可以根据Subversion访问控制文件实现更细粒度的访问控制。请注意路径可以是repos:path 或简单的path ,如果你不指定特定的版本库,访问控制规则会应用到SVNParentPath 下所有的版本库,使用的授权策略文件的格式将在第 3.1.6 节
“路径为基础的授权”描述。
3.1.5. 多版本库
如果你使用SVNParentPath指示,你就不必在每次添加新Subversion版本库时修改Apache的配置文件,只需要在第一个版本库所在的位置建立新的版本库就可以了。在我的公司,我可以使用SMB(普通的windows文件访问)直接访问服务器的文件夹,所以我直接在那里创建一个目录,运行TortoiseSVN命令
→ ,然后一个新的项目...
如果你使用Subversion 1.3或更高版本,可以使用SVNListParentPath
on 指示,这样当你使用浏览器访问父路径而不是具体某个版本库时就会显示所有版本库列表。
如果你的Subversion是早于1.3的版本,你会得到错误页,为了得到一个更好看的项目列表,你可以使用下面PHP脚本为你自动生成索引。(为了使用下面的PHP,你需要安装PHP)。
<html> <head>
<title>Subversion Repositories</title> </head>
<body> <h2>Subversion Repositories</h2>
<p> <?php $svnparentpath = "C:/svn";
$svnparenturl = "/svn"; $dh = opendir( $svnparentpath
); if( $dh ) { while( $dir = readdir( $dh ) ) { $svndir
= $svnparentpath . "/" . $dir; $svndbdir =
$svndir . "/db"; $svnfstypefile = $svndbdir
. "/fs-type"; if( is_dir( $svndir ) &&
is_dir( $svndbdir ) ) { echo "<a href=\""
. $svnparenturl . "/" . $dir . "\">"
. $dir . "</a>\n"; if( file_exists(
$svnfstypefile ) ) { $handle = fopen ("$svnfstypefile",
"r"); $buffer = fgets($handle, 4096); fclose(
$handle ); $buffer = chop( $buffer ); if( strcmp( $buffer,
"fsfs" )==0 ) { echo " (FSFS) <br
/>\n"; } else { echo " (BDB) <br />\n";
} } else { echo " (BDB) <br />\n"; }
} } closedir( $dh ); } ?> </p> </body>
</html>
3.1.6. 路径为基础的授权
mod_authz_svn模块可以根据用户名和路径实现细粒度的权限控制,对所有的Apache服务器有效,在Subversion
1.3以上版本的svnserve上也实现了路径为基础的授权。
一个可能的例子:
[groups] admin = john, kate devteam1 = john, rachel,
sally devteam2 = kate, peter, mark docs = bob, jane,
mike training = zak # Default access rule for ALL repositories
# Everyone can read, admins can write, Dan German is
excluded. [/] * = r @admin = rw dangerman = # Allow
developers complete access to their project repos [proj1:/]
@devteam1 = rw [proj2:/] @devteam2 = rw [bigproj:/]
@devteam1 = rw @devteam2 = rw trevor = rw # Give the
doc people write access to all the docs folders [/trunk/doc]
@docs = rw # Give trainees write access in the training
repository only [TrainingRepos:/] @training = rw
请注意,检查每一条路径是一件消耗极大的操作,特别是修订版本日志,服务器会检查在每一个修订版本的每一条路径是否可读,对于影响很多文件的修订将会花费很多时间。
认证和授权是不同的过程,如果用户希望获得对版本库的访问,他需要同时实现这两个步骤,对于要访问文件的普通认证请求和授权请求。
3.1.7. 使用Windows域认证
你已经注意到了,你需要为每个用户在passwd 文件中创建用户名/密码条目,如果(因为安全原因)他们希望周期性的修改他们的密码,你需要手动的做出修改。
但是对于此问题有另一个解决方案-至少是你在使用域控制器的LAN中访问版本库时:mod_auth_sspi!
最初的SSPI是由Syneapps提供的,包括源代码,但是此开发已经终止,不过不要失望,社区重新拾起代码并进行了改进,它现在的新主页在SourceForge。
- 下载这个模块,将文件
mod_auth_sspi.so 拷贝到Apache的modules目录。
- 编辑Apache的配置文件:增加行
LoadModule sspi_auth_module modules/mod_auth_sspi.so
to the LoadModule's section. Make sure you insert this
line before
the line
LoadModule auth_module modules/mod_auth.so
请注意,当你使用SSPI认证时,没有必要使用AuthUserFile 定义密码文件,Apache使用Windows域验证用户名和密码,你需要更新svnaccessfile 中的用户列表来参考DOMAIN\username 。
|
提示 |
Subversion的AuthzSVNAccessFile文件对用户名大小写敏感(“JUser”与“juser”不同)。
在微软的世界,Windows域和用户名不是大小写敏感,即使如此,一些网络管理员还是喜欢创建首字母大写的用户帐号(例如“JUser”)。
使用SSPI的一个问题是用户名和密码是用户在提示输入时发送到Subversion的,而IE经常会不管你的帐户是如何建立的都会自动发送你的用户名。
结果就是你必须为每一个用户在AuthzSVNAccessFile创建至少两个条目--一个小写的条目和一个与IE传递给Apache一样的条目,你也需要训练你的用户在通过TortoiseSVN输入访问版本库的凭证时使用小写字母。
Apache的错误和访问日志是你最好解密朋友,例如帮助你检测传递给Subversion的AuthzSVNAccessFile模块的用户名,你或许需要试验svnaccessfile中用户串的精确格式(例如DOMAIN\user 还是DOMAIN//user )来使一切工作正常。 |
|
SSL和IE |
如果你使用SSL保护你的服务器,并使用windows域来进行认证,你会发现不能使用IE浏览版本库了,不需要担心-那只是因为IE没有经过认证,其他浏览器没有这个问题,TortoiseSVN和其他Subversion客户端仍然可以得到认证。
如果你一直希望使用IE浏览你的版本库,你可以选择:
- 在Apache的配置文件定义一个单独的<Location /path>指示,添加
SSPIBasicPreferred
On ,这将使IE重新能够认证,但是其他浏览器和Subversion不能对这个location经过认证。
- 也提供未加密(没有SSL)认证的浏览,奇怪的IE在没有使用SSL的认证时没有任何问题。
- 在SSL的“标准”设置,通常在apache的虚拟SSL主机有下面的内容:
SetEnvIf User-Agent ".*MSIE.*"
\ nokeepalive ssl-unclean-shutdown \ downgrade-1.0
force-response-1.0
对这种设置有好的原因吗,见http://www.modssl.org/docs/2.8/ssl_faq.html#ToC49,但是如果你希望ntlm认证,你需要使用keepalive:http://www.microsoft.com/resources/documentation/WindowsServ/2003/standard/proddocs/en-us/qos_enablekeepalives.asp,如果你取消整个"SetEnvIf"的注释,你就可以使IE经过Win32上配置了mod_auth_sspi和SSL的认证。
|
3.1.8. 多重认证源
也可以为Subversion使用不止一个的认证源,为此,你需要将每一种认证设置为non-authoritative,这样Apache会在多个源检查用户名/密码。
一个常见的场景就是同时使用Windows域和passwd 文件认证,这样你可以为没有Windows域帐户的用户提供访问SVN的权限。
下面是结合使用Windows域&passwd 认证的完全配置:
<Location /svn> DAV svn SVNListParentPath on
SVNParentPath D:\SVN AuthName "Subversion repositories"
AuthzSVNAccessFile svnaccessfile.txt # NT Domain Logins.
AuthType SSPI SSPIAuth On SSPIAuthoritative On SSPIDomain
<domaincontroller> SSPIOfferBasic On # Htpasswd
Logins. AuthType Basic AuthAuthoritative Off AuthUserFile
passwd Require valid-user </Location>
3.1.9. 用SSL使服务器更安全
Apache服务器缺省并不支持SSL,这是因为美国的出口限制,但是你可以从其他地方下载安装。
- 首先,你需要一些文件来开启SSL,你可以在http://hunter.campbus.com/找到这些包,只需要解压缩这些文件,然后将
mod_ssl.so 拷贝到Apache的modules 目录,将文件openssl.exe 拷贝到bin 目录,将文件conf/ssl.conf 拷贝到Apache的conf 目录。
- 使用文本编辑器打开Apache的conf目录的
ssl.conf 。
- 注释掉(使用
# )下面几行:
DocumentRoot "c:/apache/htdocs"
ServerName www.example.com:443 ServerAdmin you@example.com
ErrorLog logs/error_log TransferLog logs/access_log
- 此行
SSLCertificateFile conf/ssl.crt/server.crt
改为
SSLCertificateFile conf/ssl/my-server.cert
此行
SSLCertificateKeyFile conf/ssl.key/server.key
改为
SSLCertificateKeyFile conf/ssl/my-server.key
此行
SSLMutex file:logs/ssl_mutex
改为
SSLMutex default
- 删除此行
<IfDefine SSL>
and
</IfDefine>
- 打开Apache配置文件(
httpd.conf ),并且去掉此行的注释
#LoadModule ssl_module modules/mod_ssl.so
- Openssl需要一个配置文件,你可以从http://tud.at/programm/openssl.cnf下载一个正在使用的,请注意:
*.cnf 类型的文件尽管是普通的文本文件,Windows对这种文件会特别处理!
- 然后你需要创建一个SSL证书,为此打开一个命令行窗口,进入apache目录(例如
C:\program
files\apache group\apache2 ),然后输入下面的命令:
bin\openssl req -config bin\openssl.cnf
-new -out my-server.csr
你会被讯问密语,请不要使用简单的单词,而是使用整段话,例如一段诗,越长越好。你也需要输入server的URL,其他所有问题都是可选的,但是我们建议你最好输入这些信息。
通常会自动产生
privkey.pem 文件,但是如果没有,请输入下面的命令生成它:
bin\openssl genrsa -out privkey.pem
2048
然后输入这个命令
bin\openssl rsa -in privkey.pem -out
my-server.key
并且输入(在同一行)
bin\openssl x509 -in my-server.csr
-out my-server.cert -req -signkey my-server.key -days
4000
这样会创建一个在4000天里过期的证书,最后输入:
bin\openssl x509 -in my-server.cert
-out my-server.der.crt -outform DER
这些命令在Apache目录(my-server.der.crt 、my-server.csr 、my-server.key 、.rnd 、privkey.pem 、my-server.cert )里创建了一些文件,拷贝这些文件到目录conf/ssl (例如C:\program
files\apache group\apache2\conf\ssl )-如果这个目录不存在,你需要首先创建一个。
- 重启apache服务
- 将你的浏览器指向
https://servername/svn/project
...
|
强制SSL访问 |
当你设置了SSL让你的版本库更安全,你一定希望关闭普通的非ssl访问,为此,你需要在Subversion的<Location>
增加指示:SSLRequireSSL 。
一个<Location>实例就像这个样子:
<Location /svn> DAV svn
SVNParentPath D:\SVN SSLRequireSSL AuthType Basic
AuthName "Subversion repositories" AuthUserFile
passwd #AuthzSVNAccessFile svnaccessfile Require
valid-user </Location> |
3.2. Svnserve服务器
3.2.1. 简介
有一些情况下,不能使用Apache作为你的服务器,Subversion包括Svnserve-一个轻型的独立服务器,使用普通TCP/IP连接之上的自定义协议。
大多数情况下svnserve的设置更加简单,也比Apache的服务器更加快。
3.2.2. 安装svnserve
- 从http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91得到最新版本的Subversion。
- 如果你已经安装了Subversion,svnserve已经运行,你需要在继续之前把它停下来。
- 运行Subversion安装程序,如果你在你的服务器上运行,可以跳过第4步。
- 打开资源管理器,进入Subversion的安装目录(通常是
C:\Program
Files\Subversion )的bin 目录,拷贝svnserve.exe 、libdb44.dll 、libeay32.dll 和ssleay32.dll 到你的服务器目录,例如c:\svnserve 。
3.2.3. 运行svnserve
现在svnserve已经安装了,你需要在你的server运行它,最简单的方法是在DOS窗口或者windows快捷方式输入:
svnserve.exe --daemon
svnserve将会在端口3690等待请求,--daemon选项告诉svnserve以守护进程方式运行,这样在手动终止之前不会退出。
如果你没有创建一个版本库,根据下面的Apache服务器设置指令第 3.1.4 节
“配置”。
为了验证svnserve正常工作,使用
→ 来查看版本库。
假定你的版本库位于c:\repos\TestRepo ,你的服务器叫做localhost ,输入:
svn://localhost/repos/TestRepo
当被版本库浏览器提示输入。
你也可以使用--root选项设置根位置来限制服务器的访问目录,从而增加安全性和节约输入svnserve
URL的时间:
svnserve.exe --daemon --root drive:\path\to\repository
使用前面的测试作为指南,svnserve将会运行为:
svnserve.exe --daemon --root c:\repos
然后TortoiseSVN中的版本库浏览器URL缩减为:
svn://localhost/TestRepo
注意,在svnserve和版本库位于不同分区时也需要--root选项。
|
警告 |
不要创建和访问网络共享上的Berkeley
DB版本库,它不能存在于一个远程的文件系统,即使是影射到盘符的共享。如果你希望在网络共享使用Berkeley
DB,结果难以预料-你可能会立刻看到奇怪的错误,也有可能几个月之后才发现数据库已经损坏了。 |
3.2.3.1. 以服务形式运行svnserve
如果你关心有必须有用户登录才能运行svnserve,或者担心有人关闭了svnserve而忘了重新启动,可以将svnserve设置为windows服务,从Subversion1.4开始,svnserve可以作为windows服务安装,在以前可以使用包裹器安装。
为了将svnserve安装为windows服务,执行下面的命令,就会创建一个会随windows自动启动的服务。
sc create svnserve binpath= "c:\svnserve\svnserve.exe
--service --root c:\repos" displayname= "Subversion"
depend= tcpip start= auto
|
提示 |
Microsoft现在建议服务运行于本地服务或网络服务帐户,参考The
Services and Service Accounts Security Planning
Guide。以本地服务帐户创建服务,需要在例子里追加下面几行。
obj= "NT AUTHORITY\LocalService"
请注意需要给本地服务帐户一些目录的适当权限,包括的Subversion和你的版本库,还有所有钩子脚本使用的应用。 |
为了使用包裹器安装svnserve,一个人为svnserve编写了SvnService 。Magnus
Norddahl采用了微软的骨架代码,Daniel Thompson做了进一步的改进。Daniel的版本可以从tigris.org下载。
许多更原始的工具像firedaemon也可以gognzuo
,请注意你仍然需要使用--daemon选项运行svnserve。
最后,如果你可以访问Windows 2000/XP/2003资源工具箱,你可以使用来自微软的SrvAny,这是微软官方的运行服务的方法,但是有一点混乱(需要编辑注册表),而且如果停止服务,它会直接杀掉svnserve,而不会让svnserve进行清理。如果你不想安装所有的资源工具箱,你可以只从Daniel
Petri下载SrvAny组件。
3.2.4. svnserve的认证
缺省的svnserve设置提供了匿名的只读访问,这意味着你可以使用svn:// 的URL进行检出和更新,或者使用TortoiseSVN的版本库浏览器查看版本库,但是不能提交任何修改。
为了打开对版本库的写访问,你可以编辑版本库目录的conf/svnserve.conf 文件,这个文件控制了svnserve守护进程的配置,也提供了有用的文档。
为了打开匿名的写访问,只需要简单得设置:
[general] anon-access = write
然而,你不会知道谁修改了版本库,因为svn:author 属性是空的,你也不能控制谁来修改版本库,这是一个很危险的设置。
解决这个问题的一个方法是创建密码数据库:
[general] anon-access = none auth-access = write password-db
= userfile
这里userfile 与svnserve.conf 文件在同一个目录,这个文件也可以存在于文件系统的其他地方(当多个版本库使用相同的访问权限时尤其有用),并使用绝对路径引用,或者是conf 的相对目录,使用\或盘符不能工作。userfile 的结构如下:
[users] username = password ...
这个例子拒绝所有的未认证用户(匿名)访问,给userfile 中的用户读写权限。
|
提示 |
如果维护多个版本库使用相同的密码数据库,使用一个认证域将让用户的工作更加简单,因为TortoiseSVN可以缓存你的凭证,所以你只需要输入一次,更多的信息可以看《使用Subversion进行版本控制》,对应的章节为创建用户文件和域和用户凭证缓存 |
3.2.5. 使用svn+ssh的认证
另一种svnserve认证的方法是使用SSH来建立请求通道。
通过此方法,svnserve不会作为守护进程启动,而是SSH为你启动svnserve,以SSH授权用户运行,为此,你需要在你的服务器上有SSH守护进程。
详细描述安装和设置SSH已经超过了本文的范围,然而你可以在TortoiseSVN
FAQ里查找“SSH”。
更多的关于svnserve的信息可以看使用Subversion进行版本控制。
3.2.6. svnserve以路径为基础的授权
从Subversion1.3开始,svnserve支持与mod_authz_svn 相同的路径为基础的授权模式,你需要编辑版本库路径下的conf/svnserve.conf 引用的授权文件。
[general] authz-db = authz
在这里,authz 是你创建用来定义访问权限的文件,你可以为每一个版本库使用单独的文件,或者为所有的版本库使用相同的文件,关于此文件的格式可以查看第 3.1.6 节
“路径为基础的授权”。 |