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, 存放在資料庫集群的資料目錄裡。 (HBA 的意思是 host-based authentication:基於主機的認證。) 在initdb初始化資料目錄的時候,它會安裝一個預設的文件。 不過我們也可以把認證配置文件放在其它地方;參閱 hba_file 配置參數。

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

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

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

local      database  user  authentication-method  [authentication-option]
host       database  user  CIDR-address  authentication-method  [authentication-option]
hostssl    database  user  CIDR-address  authentication-method  [authentication-option]
hostnossl  database  user  CIDR-address  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]
 

各個字串的含義如下:

local

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

host

這條記錄匹配透過 TCP/IP 進行的連線嘗試。 host 記錄匹配 SSL 和非 SSL 的連接請求。

注意: 除非伺服器帶著合適的 listen_addresses 配置參數值啟動,否則將不可能進行遠程的 TCP/IP 連接, 因為預設的行為是只監聽本地自環地址 localhost 的連接。

hostssl

這條記錄匹配使用 TCP/IP 的 SSL 連線企圖。 但必須是使用 SSL 加密的連線。

要使用這個選項,製作伺服器的時候必須打開 SSL 支援。而且在伺服器啟動的時候, 必須SSL選項透過配置選項ssl打開。 (參閱 Section 16.7 獲取更多訊息)。

hostnossl

這個記錄與 hostssl 有著正相反的邏輯: 它只匹配那些在 TCP/IP 上不使用 SSL 的連接請求。

database

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

user

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

CIDR-address

聲明這條記錄匹配的客戶端機器的 IP 地址範圍。它包含一個標準的點分十進制的 IP 地址和一個 CIDR 掩碼長度。 (IP 地址只能用數值聲明,不能用域或者主機名。) 掩碼長度資料表示客戶端 IP 地址必須匹配的高位二進制位數。 在給出的 IP 地址裡,這個長度的右邊的二進制位必須為零。 在 IP 地址,/,和 CIDR 掩碼長度之間不能有空白。

典型的 CIDR 地址是 172.20.143.89/32,這資料表明一個主機, 或者 172.20.143.0/24 資料表示一個網絡。 要聲明單個主機,給 IPv4 地址聲明 CIDR 掩碼 32,給 IPv6 地址聲明 128。

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

這個域只適用於 hosthostsslhostnossl 記錄。

IP-address
IP-mask

這些方法可以用於作為 CIDR-address 資料表示法的替補。 它不是聲明掩碼的長度,而是在另外一個字串裡聲明實際的掩碼。 比如,255.0.0.0 資料表示 IPv4 CIDR 掩碼長度 8,而 255.255.255.255 資料表示 CIDR 掩碼長度 32。 同樣的匹配邏輯將用於一個點分的 IP-mask

這些字串只適用於 hosthostssl, 和 hostnossl 記錄。

authentication-method(認證方法)

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

trust

無條件地允許連線。這個方法允許任何可以與PostgreSQL 資料庫伺服器連線的用戶以他們期望的任意 PostgreSQL 資料庫用戶身份進行連線,而不需要指令。 參閱 Section 19.2.1 獲取細節。

reject

連線無條件拒絕。常用於從一個組中"過濾"某些主機。

md5

要求客戶端提供一個 MD5 加密的指令進行認證。 參閱 Section 19.2.2 獲取細節。

crypt

要求客戶端提供一個 crypt() 加密的指令用於認證。 7.2 以前的客戶端只能支援 crypt。 對於 7.2 以及以後的客戶端,我們建議使用 md5。 參閱 Section 19.2.2 獲取細節。

password

要求客戶端提供一個未加密的指令進行認證。 因為指令是以明文形式在網絡上傳遞的, 所以我們不應該在不安全的網絡上使用這個方式。 參閱 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 關鍵字後面聲明的映射。 參閱 Section 19.2.4 獲取細節。

pam

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

authentication-option

這個可選的字串的含義取決與選擇的認證方法。細節在下面。

@ 構造包含的文件是當作一列名字讀取的, 這些名字可以用空白或者逗號分隔。註釋用 # 引入, 就像在 pg_hba.conf 裡那樣,允許嵌套 @ 構造。 除非跟在 @ 後面的文件名是一個絕對路徑,否則被當作與包含該文件的目錄相對的路徑。

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

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

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

Example 19-1. pg_hba.conf 記錄的例子

# 允許在本機上的任何用戶使用 Unix 域套接字(本地連接的預設)
# 以任何身份連線任何資料庫
# 
#
# TYPE  DATABASE    USER        CIDR-ADDRESS           METHOD
local   all         all                                trust


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

# 和上面一行相同,但是用的是獨立的掩碼字串
#
# TYPE  DATABASE    USER        IP-ADDRESS          METHOD
host    all         all         127.0.0.1     255.255.255.255     trust


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


# 允許來自主機 192.168.12.10 的用戶與 "template1" 資料庫連線,
# 只要該用戶提供了在正確的指令。
# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
host    template1   all         192.168.12.10/32      md5


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

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

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

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

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