使用mod_dav_svn访问Subversion仓库

在前面的日志中,讲述了如何使用Subversion提供的svnserve服务,通过svn://协议访问远端的仓库数据。实际上,Subversion的设计包括了一个抽象的网络层,这意味着版本库是可以通过各种服务器进程访问的。理论上来会说,Subversion可以使用无限数量的网络协议来实现,甚至可以直接用perl利用相关的接口来编写自定义协议。但日常中,用得最多的就是svn://协议,和用mod_dav_svn模块通过Apache服务进行访问。
通过HTTP协议访问版本库是Subversion的亮点之一,这种方式具备许多svnserve服务器所没有的特性,使用上更加灵活。

一、关于mod_dav_svn模块
由于Subversion需要版本化的控制,因此标准的HTTP协议不能满足需求。要让Apache与Subversion协同工作,就要使用WebDAV(Web-based Distributed Authoring and Versiong)Web分布式创作和版本控制协议。WebDAV是HTTP 1.1的扩展,关于WebDAV的规范和工作原理,可以参考IETF RFC 2518
mod_dav_san模块就是作为Subversion与Apache之间的接口,通过它,Apache就可以访问版本库,并且可以让客户端也使用HTTP的扩展协议WebDAV/DeltaV进行访问。

二、安装和配置
1、准备
与单纯的svnserve不同,要通过Apache访问Subversion,除了必须已经部署好Apache和Subversion的基本环境外,当然不可缺少的是mod_dav_svn模块了:

引用
# rpm -qa|grep svn
mod_dav_svn-1.4.2-2.1AX

2、创建版本仓库
这与以前的工作是基本相同的,不同点在于,需要让运行Apache的用户拥有该仓库的所有权:

# mkdir /var/www/svn
# cd /var/www/svn/
# svnadmin create stuff
# chown -R apache.apache stuff/

这样,就创建了一个stuff仓库,并让apache称为该仓库宿主。

3、修改Apache配置
需要激活Apache加载mod_dav_svn模块。
修改/etc/httpd/conf.d/subversion.conf配置文件的内容为:
# 加载相应的模块

引用
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so
<Location /repos>
DAV svn
SVNPath /var/www/svn/stuff
</Location>

重新启动httpd服务后,通过浏览器访问http://ip/repos,即可看到如下界面:

4、加入认证信息
上面定义的版本仓库,默认是任何人都可以匿名访问,并且拥有完全的写入、读取、修改、提交、删除版本库中信息的权限。
因此,我们需要加入认证信息以做权限的管理。HTTP协议版本就提供了简单的客户端认证方式,这可通过Apache配置完成。
Apache提供了一个htpasswd工具来管理,使用该工具可以创建一个文件,其中存放着用户名和加密后的密码信息。而这些就是Subversion可以引用的用户了,根据这些用户信息,配合mod_authz_svn模块即可进行目录的访问控制。

a、创建存放用户名信息的文件
用htpasswd命令创建文件:

引用
# mkdir /etc/svn
# htpasswd -c /etc/svn/svnusers.conf linuxing
New password:
Re-type new password:
Adding password for user linuxing

还可以利用htpasswd添加用户,或修改密码,删除用户名等:

# htpasswd -m /etc/svn/svnusers.conf NewUserName
# htpasswd -m /etc/svn/svnusers.conf OldUserName
# htpasswd -D /etc/svn/svnusers.conf OldUserName

-m 是可选的参数,当用-c创建用户名信息文件后,即可修改或添加用户信息。

b、修改/etc/httpd/conf.d/subversion.conf配置文件
在配置文件的Location标签部分,加入:

引用
# 除了下面的动作需要认证外,其他动作不需验证
<LimitExcept GET PROPFIND OPTIONS REPORT>
AuthType Basic # 使用基本认证方式,即用户名、密码认证
AuthName "Authorization Realm" # 在认证对话框中出现的提示信息
AuthUserFile /etc/svn/svnusers.conf # 指定上面创建好的存放用户名信息的文件路径
Require valid-user # 限定只有用户输入正确的用户名和密码后才能访问该标签所指向的路径
</LimitExcept>

该标签定义了,当进行除了指定的若干动作需要进行用户名和密码的认证后才能进行外,其他的动作是不做限制的。例如:只有认证用户可以写操作,同时也允许匿名的读取操作。
也可以使用<Limit >标签对特定的动作进行认证控制,甚至完全不用<Limit >或<LimitExcept >标签,表示对所有的动作进行控制。此外,定义“Require linuxing hanry”的写法,可实现将只有用户信息文件中特定的linuxing和hanry用户才能通过认证。

重启httpd服务后,可使用浏览器或svn客户端对该认证工作进行验证。


验证失败,会提示:

5、进行目录访问控制
上面配置只能对Location标签内的路径执行某些动作时进行控制,若希望控制版本仓库中目录访问权限,需要利用mod_authz_svn模块。在上面的subversion.conf中,我们已经激活了该模块。
所以,接下来要做的,就是在Location标签中使用authz功能:

引用
AuthzSVNAccessFile /etc/svn/accesspolicy.conf

其中,AuthzSVNAccessFile 指向的就是svnserve服务时使用的权限配置文件。每一段命名一个版本库和里面的路径,使用“认证用户(组)=权限”的方式描述每个用户(组)访问版本库的级别:r 是只读,rw是可读写,留空是不允许访问。另外,*表示所有用户,可以用于控制匿名用户的访问权限;@表示已经被分组的组名。
例如:

引用
# cat /etc/svn/accesspolicy.conf
[groups]
committers = paul,linuxing
developers = linuxing,hanry

[/]
* = r # 用于控制匿名用户的
@committers = rw

[/dev]
@developers = rw

[/private]
* =
@comitters = r

这里定义了两个组,并对版本库中的特定路径给予了访问权限的控制。
加入AuthzSVNAccessFile选项后,需要重启httpd服务以让其生效。但权限控制文件的内容修改后马上生效,是不需重启httpd服务。
※ 更详细的说明,还可参考前面的日志:[原]使用Subversion的svn协议访问

三、注意事项
1、如果你有多个版本仓库,怎么办?
这时,可以使用多个Location,通过SVNPath来分别指定其路径;或者,参考配置文件中提供的,用SVNParentPath指定一个总路径,例如:

引用
SVNParentPath /var/www/svn

但是,你务必需要给该总路径适当的宿主权限:

# chown -R apache.apache /var/www/svn

否则,访问时会提示权限不足的错误。接着,你就可以使用浏览器访问http://ip/repos/stuff等每个单独的版本库了。(每个单独的版本库,其Revision信息是独立的)

◎ 还需要留意两点:
a、虽然使用SVNParentPath指定了总路径,而且用浏览器去访问http://ip/repos可能会看到一些浏览信息。但如果总路径并没有加入到版本仓库中管理(即没有.svn目录下的文件),则通过svn客户端去访问版本仓库时,应通过实际仓库的路径去访问,如:http://ip/repos/stuff ;
b、使用mod_dav_svn模块,通过Apache访问版本仓库,是不需要启动svnserve服务的,一切都已经由dav模块做接口完成数据请求的工作,通过svn客户端以HTTP协议访问版本仓库即可。

2、能否通过一个权限配置文件对每个版本库进行访问权限?
Subversion提供版本库分支管理功能。因此,在svnserve服务,或使用mod_dav_svn模块,使用Apache访问Subversion版本库时,当定义权限配置文件中,是可以对每个版本库进行权限控制的。
以mod_dav_svn方式为例,像上面提到的SVNParentPath来指定版本库的总路径,如:

引用
SVNParentPath = /var/www/svn

而实际上,真正的版本库是/var/www/svn下面的一些子目录,例如/var/www/svn/project1、/var/www/svn/project2,它们才是由svnadmin create创建的版本仓库。
这时,可以在权限配置文件中,使用[repository:/path]的方式定义权限:

引用
[project1:/]
* = r
@project1_committer =rw

[project2:/]
* = r
@project2_committer =rw

3、Apache与svn权限控制该用哪个?
根据上面的描述,可以在Apache中使用<Limit>等标签进行权限控制,也可以激活mod_authz_svn模块后,使用svnauthz格式的权限文件来控制。那该如何选择呢?
事实上,它们的区别在于权限的管理者不同,对于浏览器或svn客户端来说,除了Linux文件系统本身的访问权限外,<Limit>方式是让Apache根据发送的命令进行访问管理,svnauthz则是由mod_authz_svn来进行,它们没有本质的区别,都可以用。
但由于对命令的控制比较复杂,而且容易导致误操作,因此,我更建议使用svnauthz的方式管理访问权限:

引用
<Location /repos>
DAV svn
SVNParentPath /var/www/svn
Satisfy Any
AuthType Basic
AuthName "Authorization Realm"
AuthUserFile /etc/svn/svnusers.conf
Require valid-user
AuthzSVNAccessFile /etc/svn/accesspolicy.conf
</Location>

这里的/etc/httpd/conf.d/subversion.conf文件中,不需要加入<Limit>或<LimitExcept>标签。但加入了Satisfy Any的设置,其表示在同时启用了Allow(允许)和Require的情况下,指定相关策略的,一共有两个备选值,All表示用户必须同时满足Allow和Require的条件,而Any则是满足其中之一即可。
这这里,Satisfy Any用于允许先用匿名方式尝试访问,并根据svnauthz对匿名用户的控制给予访问权限。若没有这句话,则无论svnauthz中是否加入了“*=r”的写法,匿名用户都是无法访问的。

4、svn协议与mod_authz_svn模块
svn协议,用于客户端使用svn://方式访问版本库,而mod_authz_svn模块让客户端可通过Apache访问版本库,它们分别使用不同的服务:svnserve、httpd进行访问。由于用户、组权限不同,权限管理方式也不相同,因此,不建议同时启动两种访问方式。
而易用性,管理方便的角度来分析,Apache以mod_authz_svn模块的方式访问版本库会更多人选择。(mod_authz_svn方式,使用80端口访问,并且提供https等加密传输,用于用户信息验证的密码保存方式不是明文的)

发表评论

电子邮件地址不会被公开。

*