本文档旨在描述 Subversion 1.2。如果您正在运行更新版本的 Subversion,我们强烈建议您访问 https://svnbooks.subversion.org.cn/ 并查阅适合您 Subversion 版本的书籍版本。

网络模型

本节将一般性地讨论 Subversion 客户端和服务器之间如何相互作用,无论您使用哪种网络实现。阅读完后,您将深入了解服务器的行为方式以及客户端配置响应的不同方式。

请求和响应

Subversion 客户端的大部分时间都用于管理工作副本。但是,当它需要从存储库获取信息时,它会发出网络请求,服务器会以适当的答案进行响应。网络协议的详细信息对用户隐藏;客户端尝试访问 URL,并根据 URL 模式,使用特定协议与服务器联系(参见 存储库 URL)。用户可以运行 svn --version 来查看客户端知道如何使用的 URL 模式和协议。

当服务器进程收到客户端请求时,它通常会要求客户端标识自身。它向客户端发出身份验证质询,客户端通过向服务器提供 凭据 来进行响应。身份验证完成后,服务器将以客户端请求的原始信息进行响应。请注意,此系统与 CVS 等系统不同,在 CVS 中,客户端会在发出请求之前预先向服务器提供凭据(“登录”)。在 Subversion 中,服务器在适当的时候通过向客户端发出质询来“拉取”凭据,而不是客户端“推送”凭据。这使得某些操作更加优雅。例如,如果服务器配置为允许世界上任何人都读取存储库,那么当客户端尝试 svn checkout 时,服务器永远不会发出身份验证质询。

如果客户端的网络请求将新数据写入存储库(例如 svn commit),那么将创建一个新的修订版本树。如果客户端的请求已通过身份验证,那么经过身份验证的用户的名称将作为 svn:author 属性的值存储在新的修订版本上(参见 名为“非版本化属性”的部分)。如果客户端未经身份验证(换句话说,服务器从未发出身份验证质询),那么修订版本的 svn:author 属性为空。[22]

客户端凭据缓存

许多服务器配置为要求在每次请求时进行身份验证。这可能会让用户感到厌烦,因为他们被迫一遍又一遍地输入密码。

值得庆幸的是,Subversion 客户端为此提供了解决方案:一个内置的系统,用于在磁盘上缓存身份验证凭据。默认情况下,每当命令行客户端成功响应服务器的身份验证质询时,它都会将凭据保存到用户的私有运行时配置区域中,即在类 Unix 系统上的 ~/.subversion/auth/ 或 Windows 上的 %APPDATA%/Subversion/auth/ 中。(运行时区域在 名为“运行时配置区域”的部分 中有更详细的说明。)成功的凭据将在磁盘上缓存,并根据主机名、端口和身份验证域的组合进行键控。

当客户端收到身份验证质询时,它首先会在用户的磁盘缓存中查找相应的凭据;如果找不到,或者缓存的凭据无法通过身份验证,那么客户端只需提示用户提供信息。

注重安全的人可能会在心里想,“在磁盘上缓存密码?太糟糕了!你绝不能这样做!”请保持冷静,这并不像看起来那么危险。

  • auth/ 缓存区域受到权限保护,因此只有用户(所有者)可以从中读取数据,而不是全世界的人。操作系统本身的文件权限正在保护密码。

  • 在 Windows 2000 及更高版本上,Subversion 客户端使用标准 Windows 加密服务来对磁盘上的密码进行加密。因为加密密钥由 Windows 管理,并且与用户的登录凭据绑定,所以只有用户才能解密缓存的密码。(注意:如果用户的 Windows 帐户密码被管理员重置,所有缓存的密码将无法解密。Subversion 客户端的行为将如同它们不存在一样,并在需要时提示输入密码。)

  • 对于真正偏执的,愿意牺牲所有便利的用户,可以完全禁用凭据缓存。

要禁用单个命令的缓存,请传递 --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 选项进行一些解释。许多客户端子命令接受这些选项;但是,重要的是要理解使用这些选项 不会 自动将凭据发送到服务器。如前所述,服务器在认为必要时从客户端“拉取”凭据;客户端不能随意“推送”它们。如果用户名和/或密码作为选项传递,它们将 在服务器请求它们时才会呈现给服务器。[23] 通常,这些选项用于以下情况

  • 用户想要以与其系统登录名不同的用户身份进行身份验证,或者

  • 脚本想要进行身份验证,而不使用缓存的凭据。

以下是一个最终摘要,描述了 Subversion 客户端在收到身份验证质询时的行为

  1. 检查用户是否通过 --username 和/或 --password 指定了任何凭据作为命令行选项。如果没有,或者这些选项无法成功通过身份验证,那么

  2. 在运行时 auth/ 区域中查找服务器的域,查看用户是否已经缓存了相应的凭据。如果没有,或者缓存的凭据无法通过身份验证,那么

  3. 求助于提示用户。

如果客户端通过上述任何方法成功通过身份验证,它将尝试将凭据缓存到磁盘上(除非用户已禁用此行为,如前所述)。



[22] 这个问题实际上是一个常见问题,是由服务器配置错误造成的。

[23] 同样,一个常见的错误是错误配置服务器,使其永远不会发出身份验证质询。当用户向客户端传递 --username--password 选项时,他们会惊讶地发现这些选项从未被使用,即新的修订版本似乎仍然是匿名提交的!

TortoiseSVN 官方中文版 1.14.7 发布