Chapter 4. 用户认证

Table of Contents
4.1. pg_hba.conf 文件
4.2. 认证方法
4.2.1. 信任认证
4.2.2. 口令认证
4.2.3. Kerberos 认证
4.2.4. 基于 Ident 的认证
4.2.5. PAM 认证
4.3. 认证问题

当一个客户端应用与数据库服务器进行联接时,它声明 它将以哪个 PostgreSQL 用户的名称进行联接, 就象我们登录一台 Unix 计算机 一样.在 SQL 环境里,活跃的数据库用户名决定数据库对象的各种访问 权限--参阅Chapter 6获取更多信息.因此, 实际上我们要限制的是用户可以联接的数据库.

认证 是数据库服务器建立客户端应用的标识, 然后通过一些手段判断是否允许此客户端应用(或者运行这个客户端应用的 用户)与它所要求的用户名进行联接的过程.

PostgreSQL 提供多种不同的客户端认证方式.认证某个特定客户端联接所使用的方法可以通过基于 (客户端)的主机地址,数据库和用户的方式进行选择; 一些认证方法还允许你通过用户名进行限制.

PostgreSQL 用户名在逻辑上是和 服务器运行的操作系统用户名相互独立的. 如果某个服务器的所有用户在那台服务器机器上也有帐号, 那么给数据库用户赋与操作系统用户名是有意义的.不过, 一个接收远程访问的服务器很有可能有许多没有本地帐号的用户, 因而在这种情况下数据库用户和操作系统用户名之间不必有任何联系.

4.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]
    

各个字段的含义如下:

local

这条记录匹配通过 Unix 域套接字进行的联接企图. 没有这种类型的记录,就不允许 Unix 域套接字的联接。

host

这条记录匹配通过 TCP/IP 网络进行的联接尝试.请注意,除非服务器是 带着 -i 选项或者打开了 postgresql.conf 里面的 tcpip_socket 配置参数集启动的,否则 TCP/IP 联接是被禁止掉的.

hostssl

这条记录匹配通过在 TCP/IP 上进行的 SSL 联接企图. host 记录可以匹配 SSL 和非 SSL 的联接企图, 但 hostssl 记录需要 SSL 联接。

要使用这个选项,制作服务器的时候必须打开 SSL 支持.而且在服务器启动的时候, 必须打开在postgresql.conf里的ssl选项。 (参阅 Section 3.4)。

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

对于要匹配的记录必需为零. (当然,IP地址是可以欺骗的,但是这个考虑在 PostgreSQL 的范围之外。)

这些域只适用于 hosthostssl 记录。

authentication-method(认证方法)

声明通过这条记录联接的时候使用的认证方法. 可能的选择在下面简介,详细情况在 Section 4.2

trust

无条件地允许联接.这个方法允许任何可以与PostgreSQL 数据库联接的用户以他们期望的任意 PostgreSQL 数据库用户身份进行联接,而不需要口令。 参阅 Section 4.2.1 获取细节。

reject

联接无条件拒绝.常用于从一个组中"过滤"某些主机.

md5

要求客户端提供一个 MD5 加密的口令进行认证. 这个方法是允许加密口令存储在pg_shadow里的唯一的一个方法. 参阅 Section 4.2.2 获取细节。

crypt

类似 md5 方法,只是用的是老式的 crypt 加密认证, 用于 7.2 以前的客户端.对于 7.2 以及以后的客户端,我们建议使用 md5. 参阅 Section 4.2.2 获取细节。

password

和"md5"一样,但是口令是以明文形式在网络上传递的. 我们不应该在不安全的网络上使用这个方式. 参阅 Section 4.2.2 获取细节。

krb4

用 Kerberos V4 认证用户.只有在进行 TCP/IP 联接的时候才能用. 参阅 Section 4.2.3 获取细节。 (译注:Kerberos,"克尔波洛斯",故希腊神话冥王哈得斯的多头看门狗. Kerberos 是 MIT 开发出来的基与对称加密算法的认证协议和/或密钥 交换方法.其特点是需要两个不同用途的服务器,一个用于认证身份, 一个用于通道两端用户的密钥交换.同时 Kerberos 对网络时间同步 要求比较高,以防止回放攻击,因此通常伴随 NTP 服务.)

krb5

用 Kerberos V5 认证用户.只有在进行 TCP/IP 联接的时候才能用. 参阅 Section 4.2.3 获取细节。 (译注:Kerberos V5 是上面 V4 的改良,主要是不再依赖 DES 算法, 同时增加了一些新特性.)

ident

获取客户的操作系统名(对于 TCP/IP 联接,用户的身份是通过与运行在客户端上的 ident 服务器联接进行判断的,对于本地联接,它是从操作系统获取的。) 然后检查一下,看看用户是否允许以要求的数据库用户进行联接, 方法是参照在 ident 关键字后面声明的映射。

如果你使用了 sameuser 映射,那么假设用户名 是相等的。如果没有声明这个关键字,则在与 pg_hba.conf 同目录的 pg_ident.conf 文件中找出映射名。如果这个文件里包含一条记录标识着ident提供的用户名 和请求的 PostgreSQL 用户名的映射, 那么联接被接受。

对于本地联接,只有在系统支持Unix域套接字信任证的情况下 才能使用(目前是 LinuxFreeBSDNetBSDOpenBSD, 和 BSD/OS)。

见下文Section 4.2.4获取细节。

pam

使用操作系统提供的可插入的认证模块服务 (Pluggable Authentication Modules) (PAM)来认证。参阅 Section 4.2.5 获取细节。

authentication-option

这个可选的字段的含义取决与选择的认证方法,它的描述在下一节里。

因为认证时系统是为每个联接请求顺序检查 pg_hba.conf 里的记录的,所以这些记录的顺序 是非常关键的.通常,靠前的记录有比较严的联接匹配参数和比较弱的 认证方法,而靠后的记录有比较松的匹配参数和比较严的认证方法. 比如,我们一般都希望对本地 TCP 联接使用 trust 认证, 而对远端的 TCP 联接要求口令.在这种情况下我们将 trust 认证方法用于来自 127.0.0.1 的联接,这条记录将出现在 允许更广泛的客户端 IP 地址的使用口令认证的记录前面.

Important: 不要禁止超级用户访问 template1 数据库。各种工具命令都 需要访问 template1。

在启动和 postmaster 收到SIGHUP 信号的时候, 系统都会重新装载 pg_hba.conf 文件. 如果你在活跃的系统上编辑了该文件,你就需要用 killpostmaster 发一个 SIGHUP信号,好让它重新读取该文件.

Example 4-1 里是 pg_hba.conf 的一个例子. 阅读下文理解不同认证方法的细节.

Example 4-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

# 同样,但用的是 Unix-套接字联接

local        all         all                                         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

# 允许来自主机 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