This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.

网络模型

在某些情况下, 用户需要了解 Subversion 客户端如何与服务器通信. Subversion 的网络层是抽象的, 也就是说无论服务器是什么类型, Subversion 表现出的行为总是类似的. 不管是用 HTTP 协议 (http://) 与 Apache HTTP 服务器通信, 还是传统的 Subversion 协议 ( svn://), 基本网络模式都是相同的. 本节将介绍 Subversion 网络 模式的基本概念, 包括 Subversion 如何管理授权与认证.

请求与响应

Subversion 客户端的大部分时间都用在工作副本的管理上, 当它需要从远 程仓库获取信息时, 客户端生成并向服务器发送网络请求, 服务器再用适当的回答 响应该请求. 网络协议的细节对用户是透明的—客户端试图访问一个 URL, 根据 URL 模式, 客户端将使用某种特定的协议与服务器通信.

[提示] 提示

运行 svn --version 查看客户客户端支持的 URL 模式与协议.

当服务器接收到客户端发来的请求时, 它经常会要求客户端阐明自己的身份. 服务器向客户端发送一个认证消息, 客户端提供 证书 (credentials) 进行响应, 认证一旦完成, 服务器便 向客户端返回它所请求的信息. 这与 CVS 系统不同, CVS 系统的客户端先向服 务器提供证书 (登录), 然后再发送请求. 而在 Subversion 中, 服务器在适当的时候向客户端索要证书, 在此之前客户端不会主动向服务 器发送证书, 这样的话某些操作就更加方便. 比如说如果服务器被配置成允许 任何用户读取仓库, 当客户端试图检出工作副本时 (svn checkout ), 服务器将不会要求客户端提供证书.

如果客户端发起的请求将会产生一个新的版本号 (例如 svn commit ), Subversion 就使用请求中的, 经过认证的用户名作为新的版本号 的作者, 具体来说就是把经过认证的用户名作为新版本号的 svn:author 属性值 (见 “Subversion 的保留属性”一节). 如果客户端未经过认证 (也就 是说服务器没有向客户端发送认证请求), 新版本号的 svn:author 属性值将为空.

客户端证书

很多 Subversion 服务器都会要求认证. 有时候匿名的读操作是允许的, 但是写操作必须经过认证, 还有些服务器要求读写都需要认证. 不同的 Subversion 服务器选项支持不同的认证协议, 但是从用户的视角来看, 可以 把认证简单地理解为用户名与密码. Subversion 客户端提供了几种不同的方法 来检索和存放用户的认证证书, 包括交互性地提示用户输入用户名与密码, 以及 存放在磁盘上的加密或未加密过的数据缓存.

对安全比较敏感的读者可能在想 在磁盘上缓存密码? 这可是个 馊主意, 千万不要这么干! 不用担心—并没有听起来的这么 糟糕. 下面将介绍 Subversion 使用的几种证书缓存类型, 什么时候用到它们, 以及如何禁止它们的全部或部分功能.

缓存证书

Subversion 提供了一种方法, 用于避免用户每次都要输入用户名与密码. 在默认情况下, 每当客户端成功地响应服务器的认证请求时, 认证证书都会 被缓存到磁盘上, 并把服务器的主机名, 端口与认证域的组合作为键值. 这个 缓存在将来会被自动查阅, 这就避免了用户再次输入认证证书. 如果在缓存中 没有找到合适的证书, 或者是缓存的证书认证失败, 此时客户端就会提示用户 输入用户名与密码.

Subversion 开发人员承认在磁盘上缓存认证证书有可能成为安全隐患, 为了解决这个问题, Subversion 会利用操作系统环境, 把信息泄漏的风险 降到最低.

  • 在 Windows 操作系统中, Subversion 客户端把密码存放在 %APPDATA%/Subversion/auth/ 目录内. 在 Windows 2000 及之后的系统里, 磁盘上的密码会使用标准的 Windows 加密服务进行加密. 因为密钥由 Windows 管理, 且绑定到用户个人的 登录证书, 所以只有用户才能解密缓存的密码. (如果用户的 Windows 帐户密码被管理员重置, 那么所有缓存的密码都不能再被解密, 此时 Subversion 就认为缓存密码不存在, 在需要时重新提示用户输入.)

  • 类似的, 在 Mac OS X 系统中, Subversion 用登录名作为键值存放 所有仓库的密码 (由 keychain 服务进行管理), 键值由登录密码进行 保护. 用户可以施加额外的策略, 例如每当 Subversion 要使用密码时, 就要求用户输入帐户密码.

  • 类 Unix 系统没有标准的 keychain 服务, 但 Subversion 仍然知道如何用 GNOME Keyring, KDE WalletGnuPG Agent 服务安全地 存放密码. 把未加密的密码存放在 ~/.subversion/auth/ 之前, Subversion 会询问用户是否要这么做. 注意缓存 区 auth/ 仍然受到权限的保护, 只有用户 (目录的所有者) 才能读取其中的数据. 操作系统的文件权限保护避免了密码 被系统中的其他非管理员用户看到, 当然前提是其他用户不能直接接触 存储设备或备份.

当然, 这些机制并不能完全解决问题, 对于那些为了追求安全而不惜牺牲 便利的用户来说, Subversion 提供了多种方式用于禁止证书缓存.

禁止密码缓存

用户在执行一个要求认证的操作时, Subversion 默认把密码加密后缓存 在本地, 在某些操作系统中, Subversion 可能无法进行加密, 在这种情况 下 Subversion 将会询问用户是否以明文地方式缓存证书:

$ svn checkout https://host.example.com:443/svn/private-repo
-----------------------------------------------------------------------
ATTENTION!  Your password for authentication realm:

   <https://host.example.com:443> Subversion Repository

can only be stored to disk unencrypted!  You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible.  See the documentation for details.

You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/tmp/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? 

如果用户贪图方便, 不想每次都输入密码, 那就输入 yes . 如果用户担心以明文的方式缓存密码不太安全, 而且不想每次 都被询问是否要缓存密码, 你可以永久地禁止密码明文缓存, 或者为每一个 服务器设置单独的策略.

[警告] 警告

用户在考虑如何使用 Subversion 的缓存功能时, 可能需要咨询一下 公司制度—很多公司对于如何存放员工的认证证书都有很严格的规定.

为了永久地禁止以明文方式缓存密码, 在本地配置文件 servers[global] 部分添加一行 store-plaintext-passwords = no. 为了对特定的服务器 禁止明文密码缓存, 在配置文件 servers 的适当 位置添加同样的一行 (具体的细节见 第 7 章 定制自己的 Subversion 体验“运行时配置选项”一节).

为了禁止特定的 Subversion 命令缓存密码, 向该命令添加选项 --no-auth-cache. 为了永久地禁止缓存, 在本地的 Subversion 配置文件中添加一行 store-passwords = 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

一旦找到了对应的缓存文件, 直接删除即可.

命令行认证

所有的 Subversion 命令都支持选项 --username--password, 选项的作用分别是指定用户名与密码, 这样 Subversion 就不会再提示用户输入这两项信息. 有了这两个选项, 就 可以很方便地在脚本里执行 Subversion 命令, 而不用依赖缓存的认证证书. 除此之外, 如果 Subversion 已经缓存了认证证书, 但你知道这不是你想使 用的那个 (比如多个人使用相同的登录名登录操作系统, 但每个人所使用的 Subversion 认证证书却不一样), 可以用这两个选项重新指定用户名与密码. 用户可以不指定选项 --password, 只让 Subversion 从 命令行参数中获取用户名, 但它仍然会提示用户输入与用户名对应的密码.

认证小结

关于 Subversion 的认证行为最后再讲一点, 尤其是 --username --password 这两个选项. 很多客户端子 命令都支持这两个选项, 但是要注意使用它们并不会 自动 地把证书发送给服务器, 前面已经说过, 只有当服务器认为需要 证书时, 才会主动向客户端 索要 证书, 客户端不能随心所 欲地向服务器 推送 证书. 如果在命令行选项上指定了用户 名和 (或) 密码, 只有当服务器需要时, 它们才会被递送给服务器. 使用这 两个选项的最典型情况是用户想要明确地指定用户名, 而不是让 Subversion 自己猜一个 (例如登录操作系统的用户名), 又或者是避免出现交互式的提示 信息 (例如命令是在脚本里执行的).

[注意] 注意

服务器的一个常见的配置错误是从来不向客户端发起认证请求, 如果 用户在命令行上指定了选项 --username--password, 会发现它们不起作用, 新的版本号总是 匿名提交的.

下面几点介绍了当客户端收到一个认证请求时所做的操作.

  1. 首先, 客户端检查用户是否在命令行上输入了证书 (选项 --username 和 (或) --password), 如果 是, 客户端将使用它们响应服务器的认证请求.

  2. 如果命令行参数没有提供证书, 又或者是提供的证书是无效的, 客户 端就在运行时配置的 auth/ 目录查找服务器的 主机名, 端口和认证域, 检查是否有合适的证书缓存. 如果有就使用缓存 的证书响应请求.

  3. 最后, 如果前面的认证都失败了, 客户端就会提示用户输入用户 名与密码 (除非指定了选项 --non-interactive 或 其他等效的设置).

如果客户端成功地用上面的任意一种方法满足了服务器的认证请求, 它就试图把证书缓存在本地磁盘上 (除非用户禁止了缓存).