53.3. SASL认证

53.3.1. SCRAM-SHA-256认证

SASL是一种针对面向连接协议的认证框架。当前,PostgreSQL实现了两种SASL认证机制,即SCRAM-SHA-256和SCRAM-SHA-256-PLUS。未来可能会增加更多。下面的步骤展示了通常SASL认证是如何执行的,而接下来的小节会给出更多有关SCRAM-SHA-256和SCRAM-SHA-256-PLUS的细节。

SASL认证消息流

  1. 为了开始一次SASL认证交换,服务器发送一个AuthenticationSASL消息。它包括一个服务器能够接受的SASL认证机制的列表,这个列表按照服务器喜欢的顺序组织。

  2. 客户端从该列表中选取一种受支持的机制,并且发送一个SASLInitialResponse消息给服务器。该消息包括选中的机制名称以及一个可选的初始客户端响应(如果选中的机制要用到)。

  3. 接下来将是一个或者多个服务器挑战和客户端响应消息。每一次的服务器挑战都通过一个AuthenticationSASLContinue消息发送,后面会跟着客户端通过SASLResponse消息发送的响应。这些消息的细节与机制有关。

  4. 最后,当认证交换成功完成,服务器发送一个AuthenticationSASLFinal消息,后面马上跟上一个AuthenticationOk消息。AuthenticationSASLFinal包含服务器发给客户端的额外数据,其内容与选中的认证机制有关。如果认证机制不使用在完成时发送的额外数据,则不发送AuthenticationSASLFinal消息。

在出错时,服务器可以在任何阶段中止认证,并且发送一个ErrorMessage。

53.3.1. SCRAM-SHA-256认证

目前实现的SASL机制是SCRAM-SHA-256及其带有通道绑定的变体SCRAM-SHA-256-PLUS。它们在RFC 7677RFC 5802中有详细描述。

当PostgreSQL使用SCRAM-SHA-256时,服务器将忽略客户端在client-first-message中发送的用户名,而是使用在启动消息中已经发过来的用户名。PostgreSQL支持多字符编码,然而SCRAM要求用户名使用UTF-8,因此可能无法表示PostgreSQL中的UTF-8用户名。

SCRAM规范要求口令也是UTF-8,并且要用SASLprep算法对口令进行处理。但是,PostgreSQL不要求对口令使用UTF-8。在设置一个用户的口令时,会把口令当作是UTF-8一样用SASLprep处理,而不管实际使用的编码是什么。不过,如果口令不是一种合法的UTF-8字节序列或者含有SASLprep算法禁止的UTF-8字节序列,将直接使用未被SASLprep处理过的原始口令,而不是抛出错误。这使得不是UTF-8的口令能够被规范化,但是也允许使用非UTF-8的口令,并且不要求系统了解口令到底是什么编码。

在编译了SSL支持的PostgreSQL中支持通道绑定。带有通道绑定的SCRAM的SASL机制名是SCRAM-SHA-256-PLUS。被PostgreSQL使用的通道绑定类型是tls-server-end-point

在没有通道绑定的SCRAM中,服务器选择一个随机数,它被传送给客户端,客户端会把这个随机数与用户提供的口令混合在被传输的口令哈希中。虽然这能够防止在后面的会话中成功地重新传送这个口令哈希,但是却无法防止位于真实服务器和客户端之间的伪服务器经手服务器的随机值并且认证成功。

带有通道绑定的SCRAM通过将服务器证书的签名混入被传输的口令哈希来防止这类中间人攻击。虽然伪服务器能够重新传输真实服务器的证书,但是它无法访问匹配该证书的私钥,因此无法证明它是其拥有者,进而导致SSL连接失败。

示例

  1. 服务器发送一个AuthenticationSASL消息。它包括一个服务器能够接受的SASL认证机制列表。如果服务器编译有SSL支持,这个列表将会是SCRAM-SHA-256-PLUSSCRAM-SHA-256,否则列表中只会有后者。

  2. 客户端通过发送一个SASLInitialResponse消息进行响应,该消息指出选中的机制,即SCRAM-SHA-256或者SCRAM-SHA-256-PLUS(客户端可以自由地选择机制,但是为了更安全在可以支持通道绑定变体时应该选择它)。在Initial Client响应字段中,该消息包含SCRAM的client-first-messageclient-first-message还包含客户端选中的通道绑定类型。

  3. 服务器发送一个AuthenticationSASLContinue消息,其内容是一个SCRAM的server-first message

  4. 客户端发送一个SASLResponse消息,其内容是SCRAM的client-final-message

  5. 服务器发送一个AuthenticationSASLFinal消息,其中是SCRAM的server-final-message,后面紧接着一个AuthenticationOk消息。