2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18)
開發版本: devel

50.1. 安全設計驗證器模組 #

警告

在實現驗證器模組之前,請閱讀並理解本節的全部內容。一個有故障的驗證器可能比根本沒有身份驗證更糟糕,因為它提供了虛假的安全感,並且可能導致針對 OAuth 生態系統中其他元件的攻擊。

50.1.1. 驗證器的職責 #

雖然不同的模組在令牌驗證方面可能採取截然不同的方法,但實現通常需要執行三個獨立的操作

驗證令牌

驗證器必須首先確保提供的令牌確實是用於客戶端身份驗證的有效 Bearer 令牌。正確執行此操作取決於提供者,但通常涉及加密操作以證明令牌是由受信任方建立的(離線驗證),或將令牌提供給受信任方,以便它能夠為您執行驗證(線上驗證)。

線上驗證通常透過 OAuth Token Introspection 實現,它需要驗證器模組的步驟更少,並允許在令牌被盜或錯誤頒發時進行集中吊銷。但是,這需要模組在每次身份驗證嘗試時至少進行一次網路呼叫(所有呼叫都必須在配置的 authentication_timeout 內完成)。此外,您的提供者可能不為外部資源伺服器提供內省端點。

離線驗證涉及的內容要多得多,通常需要驗證器維護提供者的受信任簽名金鑰列表,然後檢查令牌的加密簽名及其內容。實現必須嚴格遵循提供者的說明,包括任何發行者(“此令牌來自哪裡?”)、受眾(“此令牌是為誰準備的?”)和有效期(“此令牌何時可用?”)的驗證。由於模組和提供者之間沒有通訊,因此無法使用此方法集中吊銷令牌;離線驗證器實現可能希望限制令牌有效期的最大長度。

如果無法驗證令牌,模組應立即失敗。如果 Bearer 令牌不是由受信任方頒發的,那麼進一步的身份驗證/授權就毫無意義。

授權客戶端

接下來,驗證器必須確保終端使用者已授予客戶端代表他們訪問伺服器的許可權。這通常涉及檢查分配給令牌的作用域,以確保它們涵蓋當前 HBA 引數的資料庫訪問。

此步驟的目的是防止 OAuth 客戶端以虛假借口獲取令牌。如果驗證器要求所有令牌都攜帶涵蓋資料庫訪問的作用域,那麼提供者應該在流程中明確提示使用者授予該訪問許可權。這使他們有機會拒絕請求,如果客戶端不應使用其憑據連線到資料庫。

雖然可以透過利用部署架構的帶外知識來建立沒有顯式作用域的客戶端授權,但這會將使用者排除在外,從而阻止他們發現部署錯誤,並允許任何此類錯誤被靜默利用。資料庫的訪問許可權必須嚴格限制給受信任的客戶端 [17],如果使用者沒有被提示授予額外作用域。

即使授權失敗,模組也可以選擇繼續從令牌中提取身份驗證資訊,用於審計和除錯。

身份驗證終端使用者

最後,驗證器應確定令牌的使用者識別符號,方法是向提供者請求此資訊或從中提取令牌本身,並將該識別符號返回給伺服器(然後伺服器將使用 HBA 配置做出最終授權決定)。此識別符號將在會話中透過 system_user 可用,如果啟用了 log_connections,則會在伺服器日誌中記錄。

不同的提供者可能會記錄終端使用者的各種不同身份驗證資訊,通常稱為 宣告(claims)。提供者通常會記錄哪些宣告值得信任以做出授權決定,哪些不值得。 (例如,使用終端使用者的全名作為身份驗證識別符號可能不明智,因為許多提供者允許使用者任意更改其顯示名稱。)最終,選擇使用哪個宣告(或宣告組合)取決於提供者實現和應用程式需求。

請注意,透過啟用使用者對映委託,也可以實現匿名/假名登入;請參閱 第 50.1.3 節

50.1.2. 通用編碼指南 #

開發人員在實現令牌驗證時應牢記以下幾點:

令牌的機密性

模組不應將令牌或令牌的一部分寫入伺服器日誌。即使模組認為令牌無效,也應如此;混淆客戶端與其連線到錯誤提供者的攻擊者不應能夠從磁碟中檢索該(否則有效的)令牌。

在網路上傳輸令牌的實現(例如,與提供者執行線上令牌驗證)必須對等方進行身份驗證,並確保使用了強大的傳輸安全。

日誌記錄

模組可以使用與標準擴充套件相同的 日誌記錄設施;但是,在連線的身份驗證階段,將日誌條目輸出到客戶端的規則略有不同。總的來說,模組應將驗證問題記錄在 COMMERROR 級別並正常返回,而不是使用 ERROR/FATAL 來展開堆疊,以避免向未經身份驗證的客戶端洩露資訊。

可中斷性

模組必須保持可中斷訊號,以便伺服器能夠正確處理身份驗證超時和來自 pg_ctl 的關機訊號。例如,套接字上的阻塞呼叫通常應替換為處理套接字事件和中斷的程式碼,而不會出現競爭條件(請參閱 WaitLatchOrSocket()WaitEventSetWait() 等),並且長時間執行的迴圈應定期呼叫 CHECK_FOR_INTERRUPTS()。未能遵循此指南可能導致後端會話無響應。

測試

OAuth 系統的測試範圍遠超本文件的範圍,但至少,負面測試應被視為強制性的。設計一個允許授權使用者進入的模組很容易;整個系統的重點是阻止未經授權的使用者進入。

文件

驗證器實現應記錄向伺服器報告的每個終端使用者的已身份驗證 ID 的內容和格式,因為 DBA 可能需要使用此資訊來構建 pg_ident 對映。(例如,它是電子郵件地址嗎?組織 ID 號?UUID?)他們還應記錄是否可以在 delegate_ident_mapping=1 模式下安全地使用該模組,以及為了實現這一點需要哪些額外的配置。

50.1.3. 授權使用者(使用者對映委託) #

驗證器模組的標準交付物是使用者識別符號,然後伺服器將其與任何配置的 pg_ident.conf 對映 進行比較,並確定終端使用者是否被授權連線。然而,OAuth 本身就是一個授權框架,並且令牌可能包含有關使用者特權的資訊。例如,令牌可能與使用者所屬的組織組相關聯,或列出使用者可以扮演的角色,並且將這些知識複製到每個伺服器的本地使用者對映中可能不理想。

要完全繞過使用者名稱對映,並讓驗證器模組承擔授權使用者連線的其他責任,HBA 可以配置為 delegate_ident_mapping。然後,該模組可以使用令牌作用域或等效方法來決定使用者是否被允許以其期望的角色進行連線。伺服器仍將記錄使用者識別符號,但它在確定是否繼續連線方面不起任何作用。

使用此方案,身份驗證本身是可選的。只要模組報告連線已授權,即使根本沒有記錄使用者識別符號,登入也將繼續。這使得實現資料庫的匿名或假名訪問成為可能,其中第三方提供者執行所有必要的身份驗證,但不會向伺服器提供任何使用者標識資訊。(某些提供者可能會建立一個匿名 ID 號,可以代替記錄,以便以後審計。)

使用者對映委託提供了最大的架構靈活性,但它將驗證器模組變成了連線授權的單點故障。請謹慎使用。



[17] 即,“受信任”是指 OAuth 客戶端和 PostgreSQL 伺服器由同一實體控制。值得注意的是,libpq 支援的裝置授權客戶端流程通常不符合此標準,因為它設計用於公共/不受信任的客戶端。

提交更正

如果您在文件中看到任何不正確、與您對特定功能的體驗不符或需要進一步說明的內容,請使用 此表單 報告文件問題。