Chapter 19. 用戶認證

Table of Contents
19.1. pg_hba.conf 文件
19.2. 認證方法
19.2.1. 信任認證
19.2.2. 口令認證
19.2.3. Kerberos 認證
19.2.4. 基于 Ident 的認證
19.2.5. PAM 認證
19.3. 認證問題

當一個客戶端應用與數據庫服務器進行聯接時,它聲明 它將以哪個 PostgreSQL 用戶的名稱進行聯接, 就象我們登錄一台 Unix 計算機 一樣。在 SQL 環境裡,活躍的數據庫用戶名決定數據庫對象的各種訪問 權限--參閱Chapter 17獲取更多信息。因此, 實際上我們要限制的是用戶可以聯接的數據庫。

認證 是數據庫服務器建立客戶端的標識, 然後通過一些手段判斷是否允許此客戶端應用(或者運行這個客戶端應用的 用戶)與它所要求的用戶名進行聯接的過程。

PostgreSQL 提供多種不同的客戶端認證方式。認證某個特定客戶端聯接所使用的方法可以通過基于 (客戶端)的主機地址,數據庫和用戶的方式進行選擇; 一些認證方法還允許你通過用戶名進行限制。

PostgreSQL 用戶名在邏輯上是和 服務器運行的操作系統用戶名相互獨立的。 如果某個服務器的所有用戶在那台服務器機器上也有帳號, 那麼給數據庫用戶賦與操作系統用戶名是有意義的。不過, 一個接收遠程訪問的服務器很有可能有許多沒有本地操作系統帳號的用戶, 因而在這種情況下數據庫用戶和操作系統用戶名之間不必有任何聯系。

19.1. pg_hba.conf 文件

客戶端認證是由數據目錄裡的文件pg_hba.conf 控制的,比如, /usr/local/pgsql/data/pg_hba.conf。 (HBA 的意思是 host-based authentication:基于主機的認證。) 在initdb初始化數據目錄的時候,它會 安裝一個缺省的文件。

文件 pg_hba.conf 的常用格式是一套記錄, 每行一條。空白行行被忽略,井號( # )開頭的注釋 也被忽略。一條記錄是由若幹用空格和/或 tab 分隔的字段組成。 如果字段用引號包圍,那麼它可以包含空白。記錄不能誇行存在。

每條記錄聲明一種聯接類型,一個客戶端 IP 地址範圍 (如果和聯接類型相關的話),一個數據庫名,一個用戶名字, 以及對匹配這些參數的聯接使用的認證方法。 第一條匹配聯接類型,客戶端地址和聯接企圖請求的數據庫名和用戶名的記錄 將用于執行認證。這個處理過程沒有"跨越"或者 "回頭"的說法︰如果選擇了一條記錄而且認證失敗,那麼 將不考慮後面的記錄。如果沒有匹配的記錄,那麼訪問將被拒絕。

每條記錄可以下面七種格式之一

local      database  user  authentication-method  [authentication-option]
host       database  user  IP-address  IP-mask  authentication-method  [authentication-option]
hostssl    database  user  IP-address  IP-mask  authentication-method  [authentication-option]
hostnossl  database  user  IP-address  IP-mask  authentication-method  [authentication-option]
host       database  user  IP-address/IP-masklen  authentication-method  [authentication-option]
hostssl    database  user  IP-address/IP-masklen  authentication-method  [authentication-option]
hostnossl  database  user  IP-address/IP-masklen  authentication-method  [authentication-option]
 

各個字段的含義如下:

local

這條記錄匹配通過 Unix 域套接字進行的聯接企圖。 沒有這種類型的記錄,就不允許 Unix 域套接字的聯接。

host

這條記錄匹配通過 TCP/IP 網絡進行的聯接嘗試。請注意,除非服務器是 帶著 -i 選項或者打開了 tcpip_socket 配置參數集啟動的,否則 TCP/IP 聯接是被禁止掉的。

hostssl

這條記錄匹配通過在 TCP/IP 上進行的 SSL 聯接企圖。 host 記錄可以匹配 SSL 和非 SSL 的聯接企圖, 但 hostssl 記錄需要 SSL 聯接。

要使用這個選項,制作服務器的時候必須打開 SSL 支持。而且在服務器啟動的時候, 必須打開ssl選項。 (參閱 Section 16.4 獲取更多信息)。

hostnossl

這個記錄類似hostssl,但是作用正相反:它只匹配那些 不使用 SSL 的連接請求。

database

聲明記錄所匹配的數據庫。值 all 表明該記錄匹配所有數據庫, 值 sameuser表示如果被請求的數據庫和請求的用戶同名,則匹配。 samegroup 表示請求的用戶必須是一個與數據庫同名的組中的成員。 在其他情況裡,這就是一個特定的 PostgreSQL 的名字。 我們可以通過用逗號分隔的方法聲明多個數據庫。 一個包含數據庫名的文件可以 通過對該文件前綴 @ 來聲明。該文件必需和 pg_hba.conf 在同一個目錄。

user

為這條記錄聲明所匹配的PostgreSQL用戶。值 all 表明它匹配 于所有用戶。否則,它就是特定 PostgreSQL 用戶的名字。多個用戶名可以通過用逗號分隔的方法聲明。組名字 可以通過用 + 做組名字前綴來聲明。一個包含用戶名的文件可以 通過在文件名前面前綴 @ 來聲明。該文件必需和 pg_hba.conf 在同一個目錄。

IP-address
IP-mask

這兩個字段包含標準的點分十進制表示的 IP地址/掩碼值。 (IP地址只能用數字的方式聲明,而不能用域名或者主機名。) 它們倆放在一起,聲明了這條記錄匹配的客戶機的 IP 地址。 準確的邏輯是

(actual-IP-address xor IP-address-field) and IP-mask-field

對于要匹配的記錄必需為零。

以 IPv4 格式給出的 IP 地址會匹配那些擁有對應地址的 IPv6 連接,比如 127.0.0.1 將匹配 IPv6 地址 ::ffff:127.0.0.1。 一個以 IPv6 格式給出的記錄將只匹配 IPv6 連接,即使對應的地址在 IPv4-in-IPv6 範圍內。請注意如果系統的 C 庫不支持 IPv6 地址,那麼 IPv6 的格式將被 拒絕。

這些域只適用于 hosthostsslhostnossl 記錄。

IP-masklen

這個域可以用于作為 IP-mask 表示法的 替補。它是一個整數,聲明在掩碼中設置的從高向低排的掩碼位數。 這個數值必須介于 0 和 32 (對應 IPv4 地址)或者 128 (對應IPv6地址)之間。 (包含32 和 128)。0 將匹配任意地址,兒 32 (或者是 128)將只匹配一個主機。 同樣的匹配邏輯將用于一個點分的 IP-mask

IP-address/ 或者 /IP-masklen 之間不能有空白,否則文件將無法正確分析。

這個字段只適用于 hosthostssl, 和 hostnossl 記錄。

authentication-method(認證方法)

聲明通過這條記錄聯接的時候使用的認證方法。 可能的選擇在下面簡介,詳細情況在 Section 19.2

trust

無條件地允許聯接。這個方法允許任何可以與PostgreSQL 數據庫服務器聯接的用戶以他們期望的任意 PostgreSQL 數據庫用戶身份進行聯接,而不需要口令。 參閱 Section 19.2.1 獲取細節。

reject

聯接無條件拒絕。常用于從一個組中"過濾"某些主機。

md5

要求客戶端提供一個 MD5 加密的口令進行認證。 這個方法是允許加密口令存儲在pg_shadow裡的唯一的一個方法。 參閱 Section 19.2.2 獲取細節。

crypt

類似 md5 方法,只是用的是老式的crypt()加密認證, 用于 7.2 以前的客戶端。對于 7.2 以及以後的客戶端,我們建議使用 md5。 參閱 Section 19.2.2 獲取細節。

password

md5一樣,但是口令是以明文形式在網絡上傳遞的。 我們不應該在不安全的網絡上使用這個方式。 參閱 Section 19.2.2 獲取細節。

krb4

用 Kerberos V4 認證用戶。只有在進行 TCP/IP 聯接的時候才能用。 參閱 Section 19.2.3 獲取細節。 (譯注:Kerberos,"克爾波洛斯",故希臘神話冥王哈得斯的多頭看門狗。 Kerberos 是 MIT 開發出來的基與對稱加密算法的認證協議和/或密鑰 交換方法。其特點是需要兩個不同用途的服務器,一個用于認證身份, 一個用于通道兩端用戶的密鑰交換。同時 Kerberos 對網絡時間同步 要求比較高,以防止回放攻擊,因此通常伴隨 NTP 服務。)

krb5

用 Kerberos V5 認證用戶。只有在進行 TCP/IP 聯接的時候才能用。 參閱 Section 19.2.3 獲取細節。 (譯注:Kerberos V5 是上面 V4 的改良,主要是不再依賴 DES 算法, 同時增加了一些新特性。)

ident

獲取客戶的操作系統名(對于 TCP/IP 聯接,用戶的身份是通過與運行在客戶端上的 ident 服務器聯接進行判斷的,對于本地聯接,它是從操作系統獲取的。) 然後檢查一下,看看用戶是否允許以要求的數據庫用戶進行聯接, 方法是參照在 ident 關鍵字後面聲明的映射。

如果你使用了 sameuser 映射,那麼要求用戶名 是相等的。如果沒有聲明這個關鍵字,則在與 pg_hba.conf 同目錄的 pg_ident.conf 文件中找出映射名。如果這個文件裡包含一條記錄標識著操作系統提供的用戶名 和請求的 PostgreSQL 用戶名的映射, 那麼聯接被接受。

對于本地聯接,只有在系統支持Unix域套接字信任證的情況下 才能使用(目前是 LinuxFreeBSDNetBSDOpenBSD, 和 BSD/OS)。

見下文Section 19.2.4獲取細節。

pam

使用操作系統提供的可插入的認證模塊服務 (Pluggable Authentication Modules) (PAM)來認證。參閱 Section 19.2.5 獲取細節。

authentication-option

這個可選的字段的含義取決與選擇的認證方法,它的描述在下一節裡。

因為認證時系統是為每個聯接請求順序檢查 pg_hba.conf 裡的記錄的,所以這些記錄的順序 是非常關鍵的。通常,靠前的記錄有比較嚴的聯接匹配參數和比較弱的 認證方法,而靠後的記錄有比較鬆的匹配參數和比較嚴的認證方法。 比如,我們一般都希望對本地 TCP/IP 聯接使用 trust 認證, 而對遠端的 TCP/IP 聯接要求口令。在這種情況下我們將 trust 認證方法用于來自 127.0.0.1 的聯接,這條記錄將出現在 允許更廣泛的客戶端 IP 地址的使用口令認證的記錄前面。

Important: 不要禁止超級用戶訪問template1數據庫。各種工具命令都 需要訪問template1

在啟動和主服務器進程( postmaster )收到SIGHUP 信號的時候, 系統都會重新裝載 pg_hba.conf 文件。 如果你在活躍的系統上編輯了該文件,你就需要用 killpostmaster 發一個 SIGHUP信號,好讓它重新讀取該文件。

Example 19-1 裡是 pg_hba.conf 的一個例子。 閱讀下文理解不同認證方法的細節。

Example 19-1. 一個 pg_hba.conf 文件的例子

# 允許在本機上的任何用戶使用 Unix 域套接字(本地連接的缺省)
# 以任何身份聯接任何數據庫
# 
#
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
local   all         all                                             trust


# 和上面相同,但是使用的是自環的(loopback)TCP/IP 連接
# 
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
host         all         all        127.0.0.1     255.255.255.255    trust

# 和上面一行相同,但是用的是 CIDR 掩碼
#
# TYPE  DATABASE    USER        IP-ADDRESS/CIDR-mask  METHOD
host    all         all         127.0.0.1/32          trust


# 允許 IP 地址為 192.168.93.x 的任何主機與數據庫
# "template1" 相連,用與他們在自己的主機上相同 ident 的用戶名標識他自己
# (通常是他的 Unix 用戶名)
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
host    template1   all         192.168.93.0      255.255.255.0     ident sameuser

# 和上面一行相同,但是用的是 CIDR 掩碼
#
# TYPE  DATABASE    USER        IP-ADDRESS/CIDR-mask  METHOD
host    template1   all         192.168.93.0/24       ident sameuser


# 允許來自主機 192.168.12.10 的用戶與 "template1" 數據庫聯接,
# 只要該用戶提供了在正確的口令。
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
host    template1   all         192.168.12.10     255.255.255.255   md5

# 如果前面沒有其它 "host" 行,那麼下面兩行將拒絕所有來自
# 192.168.54.1 的聯接請求 (因為前面的記錄先匹配
# 但是允許來自互聯網上其它任何地方的有效的 Kerberos V5 認證的聯接
# 零掩碼表示不考慮主機 IP 的任何位。因此它匹配任何主機:
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
host    all         all         192.168.54.1      255.255.255.255   reject
host    all         all         0.0.0.0           0.0.0.0           krb5

# 允許來自 192.168.x.x 的任何用戶與任意數據庫聯接,只要他們通過 ident 檢查
# 但如果 ident 說該用戶是 "bryanh" 而他要求以 PostgreSQL 用戶 "guest1" 聯接,
# 那麼只有在 `pg_ident.conf' 裡有 "omicron" 的映射,說 "bryanh" 允許以
#  "guest1" 進行聯接時才真正可以進行聯接。
#
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
host    all         all         192.168.0.0       255.255.0.0       ident omicron

# 如果下面是用于本地聯接的僅有的三行,那麼它們將允許本地用戶
# 只和它們自己的數據庫聯接(數據庫名和用戶名同名),
# 只有管理員和組"support"裡的成員例外,他們可以聯接到任何數據庫。
# 文件 $PGDATA/admins 列出了那些允許與所有數據庫聯接的用戶名。
# 在所有情況下都需要口令。
# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD
local   sameuser    all                                             md5
local   all         @admins                                         md5
local   all         +support                                        md5

# 上面最後兩行可以合起來寫成一行
local   all         @admins,+support                                md5

# 數據庫字段也可以使用列表和文件名,但組不行:
local   db1,db2,@demodbs  all                                       md5