代理的地址告诉 Emacs 连接到哪里,而登录是这段对话的另一部分。对于普通的 HTTP 请求,Emacs 的 URL 库可以应答代理的认证质询,从 auth-source 获取凭据或交互式询问,并复用会话中保存的凭据。

下面的细节依据 Emacs 31.1。它们针对使用URL 库的操作;由 Emacs 包启动的外部下载器有自己的认证路径。

先设定路由,再让 HTTP 去索要登录

固定的代理端点可以用文档中给出的选项来指定:

(setq url-proxy-services
      '(("http" . "proxy.example:8080")
        ("https" . "proxy.example:8080")))

把占位符换成实际提供的端点。键描述的是目标 URL 的方案。加入 HTTPS 项只是为 HTTPS 目标选择路由,它本身并不提供凭据。

在普通 HTTP 请求过程中,代理可能以 407 Proxy Authentication Required 和 Proxy-Authenticate 质询作答。URL 库会选择一个受支持的认证方案,为该代理端点取得凭据,然后用 Proxy-Authorization 重试。

对于 Basic 认证,当没有合适的凭据时,交互式请求可以询问用户名和密码。标记为非交互的请求则不能依赖这些提示。代理登录也与目标网站的登录相互独立:网站的 401 质询走的是另一条路径。

把长期凭据放进 auth-source

如果 auth-source 已经在读取 ~/.authinfo.gpg 这样的加密凭据文件,本示例的 Basic 条目形如:

machine proxy.example port http login YOUR_LOGIN password YOUR_PASSWORD

请使用真实的账户与密钥,并确保该文件属于你配置的 auth-sources。这一行只是说明匹配字段,并不是让你把密码写进 Lisp 初始化文件。

Emacs 31.1 的 Basic 实现有两点值得注意。它查找代理主机名时不带数字 TCP 端口,并把代理 URL 的方案当作 auth-source 的端口值传入。对这个 HTTP 代理来说,该值是 http,尽管 TCP 连接使用的是 8080 端口。

这次查找不包含质询的 realm,也不包含数字代理端口。不要指望它能就同一主机名上的多个 realm 或代理端口选出不同的 Basic 密码。Digest 使用另一套主机查找,因此上面的示例专门针对 Basic。

URL 库还维护自己的认证缓存。它的 Basic 条目会区分代理端点,并在端点内部按 realm 或目录匹配;该缓存与 auth-source 查找是分开的。在提示处输入密码可以填充会话缓存,而不会在你的长期凭据文件中新增条目。

HTTPS 有一个更早的认证步骤

对于经由 HTTP 代理访问 HTTPS 目标,Emacs 会先发送 CONNECT。因此在到达与网站的加密连接之前,可能就需要完成认证。

在 Emacs 31.1 中,CONNECT 请求的构造器会检查其认证机制已经可用的认证,包括缓存中的 Basic 凭据。它的 Basic 路径此时既不会询问、也不会取来新的 auth-source 条目。非 200 的 CONNECT 响应同样不会进入上文所述的常规 HTTP 407 质询处理程序。

因此,一个能应答普通 HTTP Basic 质询的 auth-source 条目,并不能保证新会话的第一次 HTTPS 请求就能认证成功。带有合适缓存凭据的会话,初始状态并不相同。反复修改同一条密码记录,本身并不能消除两条路径之间的这一差异。

如果某次 HTTPS 操作停在代理处,先确认 CONNECT 是否收到了 407,以及你是否在使用这个版本的行为。同时确认代理所提供的认证方案。Basic 凭据条目并不是适配所有企业认证系统的通用转接器。

把持久配置放在公开的代理选项和你选定的凭据后端里。URL 库内部的 Basic 存储有助于理解这一行为,但手工填充那个私有数据结构会把配置绑定到实现细节上。

相关文章