SASL是面向连接的协议中用于认证的框架。目前,PostgreSQL实现了两种SASL认证机制,SCRAM-SHA-256和SCRAM-SHA-256-PLUS。将来可能会添加更多。下面的步骤说明了SASL认证的一般执行过程,而下一小节将更详细地介绍SCRAM-SHA-256和SCRAM-SHA-256-PLUS。
SASL 认证消息流
要开始一个 SASL 认证交换,服务器发送一个 AuthenticationSASL 消息。它包括服务器可以接受的 SASL 认证机制列表,按照服务器的首选顺序排列。
客户端从列表中选择一个支持的机制,并向服务器发送一个 SASLInitialResponse 消息。该消息包括所选机制的名称,以及如果所选机制使用的话,还包括一个可选的初始客户端响应。
一个或多个服务器挑战和客户端响应消息将随后而来。每个服务器挑战都是在一个 AuthenticationSASLContinue 消息中发送的,随后是客户端在一个 SASLResponse 消息中的响应。这些消息的具体内容是特定于机制的。
最后,当认证交换成功完成时,服务器发送一个AuthenticationSASLFinal消息,紧接着是一个AuthenticationOk消息。 AuthenticationSASLFinal包含额外的服务器到客户端的数据,其内容特定于所选的认证机制。 如果认证机制不使用在完成时发送的额外数据,那么AuthenticationSASLFinal消息就不会被发送。
在错误情况下,服务器可以在任何阶段中止认证,并发送一个ErrorMessage。
目前实现的SASL机制是SCRAM-SHA-256及其带有通道绑定的变体
SCRAM-SHA-256-PLUS。它们在
RFC 7677
和RFC 5802中有详细描述。
当在 PostgreSQL 中使用 SCRAM-SHA-256 时,服务器将忽略客户端在
client-first-message 中发送的用户名。
而是使用已经在启动消息中发送的用户名。
PostgreSQL 支持多种字符编码,而 SCRAM 规定用户名必须使用 UTF-8,
因此可能无法用 UTF-8 表示 PostgreSQL 用户名。
SCRAM 规范规定密码也必须是 UTF-8 编码,并且使用 SASLprep 算法处理。 然而,PostgreSQL 不要求密码必须使用 UTF-8 编码。 当用户设置密码时,无论实际使用的编码是什么,都会像使用 UTF-8 一样使用 SASLprep 进行处理。 但是,如果密码不是合法的 UTF-8 字节序列,或者包含 SASLprep 算法禁止的 UTF-8 字节序列, 则会使用原始密码而不进行 SASLprep 处理,而不是抛出错误。这样可以在密码为 UTF-8 时对其进行规范化, 但仍允许使用非 UTF-8 密码,并且不需要系统知道密码使用的编码方式。
Channel binding 在支持 SSL 的 PostgreSQL 构建中受支持。
带有通道绑定的 SCRAM 的 SASL 机制名称是 SCRAM-SHA-256-PLUS。
PostgreSQL 使用的通道绑定类型是 tls-server-end-point。
在没有通道绑定的SCRAM中,服务器选择一个随机数, 传输给客户端,与用户提供的密码在传输的密码哈希中混合。虽然这可以 防止密码哈希在后续会话中被成功重新传输,但无法阻止真实服务器和客 户端之间的虚假服务器通过服务器的随机值并成功进行身份验证。
SCRAM与通道绑定一起防止这种中间人攻击,通过将服务器证书的签名混合到传输的密码哈希中。 虽然伪造服务器可以重新传输真实服务器的证书,但它无法访问与该证书匹配的私钥,因此无法证明自己是所有者,导致SSL连接失败。
示例
服务器发送一个AuthenticationSASL消息。它包括服务器可以接受的SASL认证机制列表。
如果服务器构建时支持SSL,这将是SCRAM-SHA-256-PLUS和SCRAM-SHA-256,
否则只是后者。
客户端通过发送SASLInitialResponse消息做出响应,该消息指示选择的机制,SCRAM-SHA-256或SCRAM-SHA-256-PLUS。
(客户端可以自由选择任一机制,但为了更好的安全性,如果支持的话应选择通道绑定变体。)
在初始客户端响应字段中,消息包含SCRAM client-first-message。
client-first-message还包含客户端选择的通道绑定类型。
服务器发送一个AuthenticationSASLContinue消息,其中包含一个SCRAMserver-first-message作为内容。
客户端发送一个SASLResponse消息,其中包含SCRAM
client-final-message作为内容。
服务器发送一个AuthenticationSASLFinal消息,带有SCRAM
server-final-message,紧接着是一个AuthenticationOk消息。