网络模型

本节是对Subversion客户机和服务器如何交互的一般性讨论,无论你在使用什么网络实现。在读完后,你将对服务器如何运转和 客户端可配置的不同响应方式有一个很好的理解。

请求和响应

Subversion客户端大部分时间用于管理工作副本。但是当它需要来自资料库的信息时,它发起一个网络请求,服务器回应以合适的答案。 网络协议的细节对用户隐藏了;客户端尝试访问一个URL,根据URL模式来使用特定的协议来联系服务器(参见 资料库URL)。用户可以运行 svn --version 来查看客户端懂得使用哪些URL模式和协议。

当服务器进程接收到一个客户端请求时,它通常需要客户端自身的标识。它向客户端发出一个认证质询,客户端回应给服务器认证凭证(credentials)。 一旦认证完成,服务器将回应给客户端它原本要求的信息。注意这个系统和CVS这样的系统不同,那些系统里客户端在发起请求前就需要 提前提供凭证(“登录log in”)。在Subversion里,服务器通过在适当的时候向客户端发起要求来“拉入”凭证, 而不是靠客户端来“推入”他们。这使得某些操作更加优雅。例如,如果服务器被配置为允许世界上的任何人来读资料库, 那么在客户端企图 svn checkout时,这服务器将永不会提出认证要求。

如果客户端发起的网络请求要往资料库里写新数据(比如,svn commit),那么一个新修订版树被创建。如果客户端请求被 认证了,那么认证的用户名被存储为这个新修订版的svn:author属性的值(参见“未版本化的属性”一节)。如果客户端没有认证(换句话说,服务器从来没有要求认证),那么修订版的svn:author属性是空的。 [18]

客户凭证缓存

很多服务器被配置为每个请求都需要认证。这对用户会成为很大的烦恼:他们被迫一次又一次的敲入他们的密码。

值得高兴的是,Subversion客户端对这问题有个补救:一个内建在磁盘上缓存认证凭证的系统。缺省情况下,一旦命令行客户端成功的在一个服务器 认证了自己,它将在用户的私有运行时配置区域——在Unix类系统上是~/.subversion/auth/,或在Windows上的 %APPDATA%/Subversion/auth/——保存这些凭证(运行时区域在???更详细的谈到)。成功的凭证被缓存到磁盘上,以主机名,端口和认证区域的结合作为键。

当客户端接到认证要求时,它首先在磁盘缓存里寻找合适的凭证,如果缓存的凭证认证失败,那么客户端就提示用户输入这些信息。

安全狂热的人们可能心中盘算,“在磁盘上缓存密码?太可怕了!你永远不应该这么做!”但是请保持镇静。首先, auth/缓存区域是有权限保护的,因此只有这个用户(所有者)才能从这里读数据,在不是整个世界。 如果对你来说这还不够安全,你可以禁止证书缓存。要在某个命令上禁止缓存,可以传递--no-auth-cache选项给它:

$ svn commit -F log_msg.txt --no-auth-cache
Authentication realm: <svn://host.example.com:3690> example realm
Username:  joe
Password for 'joe':

Adding         newfile
Transmitting file data .
Committed revision 2324.

# password was not cached, so a second commit still prompts us

$ svn delete newfile
$ svn commit -F new_msg.txt
Authentication realm: <svn://host.example.com:3690> example realm
Username:  joe
[...]

或者,如果你想永久禁止证书缓存,那么你可以编辑你的运行时 config文件(位于auth/ 目录里面)。只要把store-auth-creds设为no,那么证书文件将不再被缓存。

[auth]
store-auth-creds = no

有时用户会想要从磁盘缓存里删掉某些特定的凭证。为了这个目的,你需要到auth/区域里手工删除适当的缓存文件。 证书用单独的文件来缓存;如果你查看每个文件里面,你会看到键和值。svn:realmstring键描述了该文件关联的特定的 服务器区域。

$ ls ~/.subversion/auth/svn.simple/
5671adf2865e267db74f09ba6f872c28        
3893ed123b39500bca8a0b382839198e
5c3c22968347b390f349ff340196ed39

$ cat ~/.subversion/auth/svn.simple/5671adf2865e267db74f09ba6f872c28

K 8
username
V 3
joe
K 8
password
V 4
blah
K 15
svn:realmstring
V 45
<https://svn.domain.com:443> Joe's repository
END

一旦你找到了正确的缓存文件,删除它就可以了。

关于客户端认证行为的最后一点说明:需要稍微解释一下--username--password选项。很多客户端 子命令接受这些选项;但是重要的是要理解使用这些选项不会自动的发送凭证到服务器。如同在前面讨论过的, 服务器在它认为需要的时候从客户端“”证书;客户端不能随意的“”它们。如果用户和密码作为参数被传入, 它们将在服务器要求的时候被呈现给它。 [19] 通常,这些选项在这些情况下使用:

  • 用户想以不同于她的系统登陆名的用户来认证,或者

  • 一个脚本想不用缓存的证书来认证。

这里是一个最终的总结,描述了Subversion客户端在收到认证要求时的行为:

  1. 检查用户是否在命令行选项中通过--username和/或--password指定了任何认证信息。如果没有, 或者如果这些选项没能通过认证,那么

  2. 检查在运行时auth/区域中的服务器领域,来查看是否用户已经有缓存的适当的凭证。如果没有,或如果缓存的 凭证没有通过认证,那么

  3. 最后再提示用户输入。

如果客户端用上列任何办法认证成功,那么它将尝试在磁盘上缓存凭证(如果用户没有如前面提到的那样禁止这种行为的话)。



[18] 这个问题实际上是一个FAQ,来自于一个错误配置的服务器设置。

[19] 还有,一个常见的错误是错误配置了服务器而导致它从不提出认证要求。当用户传递--username--password选项给客户程序时,他们看到这些没被使用会非常惊讶,就是说,新修订版仍然表现出被匿名 提交的样子!