SASL 是面向連線協議中用於身份驗證的框架。目前,PostgreSQL 支援三種 SASL 身份驗證機制:SCRAM-SHA-256、SCRAM-SHA-256-PLUS 和 OAUTHBEARER。未來可能會新增更多機制。以下步驟說明了 SASL 身份驗證的通用流程,而後續小節將詳細介紹特定機制。
SASL 身份驗證訊息流
為了開始 SASL 身份驗證交換,伺服器會發送一個 AuthenticationSASL 訊息。該訊息包含伺服器可以接受的 SASL 身份驗證機制列表,按伺服器偏好的順序排列。
客戶端從列表中選擇一個支援的機制,並向伺服器傳送 SASLInitialResponse 訊息。該訊息包含所選機制的名稱,以及可選的初始客戶端響應(如果所選機制使用該響應)。
隨後將傳送一個或多個伺服器挑戰和客戶端響應訊息。每個伺服器挑戰都透過 AuthenticationSASLContinue 訊息傳送,接著是客戶端在 SASLResponse 訊息中的響應。訊息的具體內容因機制而異。
最後,當身份驗證交換成功完成時,伺服器會發送一個可選的 AuthenticationSASLFinal 訊息,然後立即傳送 AuthenticationOk 訊息。AuthenticationSASLFinal 包含伺服器到客戶端的附加資料,其內容特定於所選的身份驗證機制。如果身份驗證機制在完成時未傳送附加資料,則不傳送 AuthenticationSASLFinal 訊息。
發生錯誤時,伺服器可以在任何階段中止身份驗證,併發送 ErrorMessage。
SCRAM-SHA-256
及其帶有通道繫結的變體 SCRAM-SHA-256-PLUS
是基於密碼的身份驗證機制。它們在 RFC 7677 和 RFC 5802 中有詳細描述。
當 SCRAM-SHA-256 在 PostgreSQL 中使用時,伺服器將忽略客戶端在 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 密碼,並且不需要系統知道密碼的編碼。
通道繫結 在支援 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 訊息,其內容為 SCRAM server-first-message
。
客戶端傳送一個 SASLResponse 訊息,其內容為 SCRAM client-final-message
。
伺服器傳送一個 AuthenticationSASLFinal 訊息,其中包含 SCRAM server-final-message
,然後立即傳送一個 AuthenticationOk 訊息。
OAUTHBEARER
是一種基於令牌的聯合身份驗證機制。它在 RFC 7628 中有詳細描述。
典型的交換過程根據客戶端是否已經為當前使用者快取了持有者令牌而有所不同。如果客戶端沒有快取令牌,則交換將透過兩個連線進行:第一個“發現”連線用於從伺服器獲取 OAuth 元資料,第二個連線用於在客戶端獲取令牌後傳送令牌。(libpq 目前在其內建流程中不實現快取方法,因此它使用雙連線交換。)
此機制是客戶端發起的,類似於 SCRAM。客戶端初始響應包括 SCRAM 使用的標準“GS2”標頭,後跟一個 key=value
對列表。伺服器目前支援的唯一鍵是 auth
,它包含持有者令牌。OAUTHBEARER
額外指定了客戶端初始響應的三個可選元件(GS2 標頭的 authzid
,以及 host
和 port
鍵),這些元件目前被伺服器忽略。
OAUTHBEARER
不支援通道繫結,也沒有“OAUTHBEARER-PLUS”機制。此機制在成功身份驗證期間不使用伺服器資料,因此在交換過程中不使用 AuthenticationSASLFinal 訊息。
示例:
在第一次交換期間,伺服器會發送一個 AuthenticationSASL 訊息,其中廣告宣傳了 OAUTHBEARER
機制。
客戶端透過傳送 SASLInitialResponse 訊息進行響應,該訊息指示 OAUTHBEARER
機制。假設客戶端尚未為當前使用者持有有效的持有者令牌,則 auth
欄位為空,表示這是發現連線。
伺服器傳送一個 AuthenticationSASLContinue 訊息,其中包含一個錯誤 status
以及客戶端應使用的用於進行 OAuth 流程的通用 URI 和範圍。
客戶端傳送一個 SASLResponse 訊息,其中包含空集(一個 0x01
位元組)以完成其在發現交換中的部分。
伺服器傳送一個 ErrorMessage 以中止第一次交換。
此時,客戶端將執行多種可能的 OAuth 流程之一來獲取持有者令牌,除了伺服器提供的元資料外,還可以使用任何配置給它的元資料。(此描述故意保持模糊;OAUTHBEARER
不指定或強制要求任何特定的獲取令牌的方法。)
一旦獲得令牌,客戶端將重新連線到伺服器進行最終交換
伺服器再次傳送一個 AuthenticationSASL 訊息,其中廣告宣傳了 OAUTHBEARER
機制。
客戶端透過傳送 SASLInitialResponse 訊息進行響應,但這次訊息中的 auth
欄位包含在客戶端流程中獲取的持有者令牌。
伺服器根據令牌提供商的指示驗證令牌。如果客戶端被授權連線,則傳送 AuthenticationOk 訊息以結束 SASL 交換。
如果您在文件中看到任何不正確之處,與您對特定功能的體驗不符,或需要進一步澄清,請使用 此表格 報告文件問題。