ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 19.1\. `pg_hba.conf`文件 客户端认证是由一个配置文件(通常名为`pg_hba.conf`)控制的, 它存放在数据库集群的数据目录里。HBA的意思是"host-based authentication", 也就是基于主机的认证。在`initdb`初始化数据目录的时候, 它会安装一个缺省的`pg_hba.conf`文件。不过我们也可以把认证配置文件放在其它地方; 参阅[hba_file](#calibre_link-1558)配置参数。 `pg_hba.conf`文件的常用格式是一组记录,每行一条。空白行将被忽略, 井号`#`开头的注释也被忽略。记录不能跨行存在。 一条记录是由若干用空格和/或制表符分隔的字段组成。如果字段用引号包围,那么它可以包含空白。 在数据库、用户或地址文件中引用一个关键词(如,`all` 或 `replication`) 使这个词失去它的特殊角色,只是用这个名字匹配一个数据库、用户或主机。 每条记录声明一种连接类型、一个客户端 IP 地址范围(如果和连接类型相关的话)、 一个数据库名、一个用户名字、对匹配这些参数的连接使用的认证方法。第一条匹配连接类型、 客户端地址、连接请求的数据库名和用户名的记录将用于执行认证。这个处理过程没有 "跨越"或者"回头"的说法:如果选择了一条记录而且认证失败, 那么将不再考虑后面的记录。如果没有匹配的记录,那么访问将被拒绝。 每条记录可以是下面七种格式之一: ``` local _database_ _user_ _auth-method_ [`_auth-options_`] host _database_ _user_ _address_ _auth-method_ [`_auth-options_`] hostssl _database_ _user_ _address_ _auth-method_ [`_auth-options_`] hostnossl _database_ _user_ _address_ _auth-method_ [`_auth-options_`] host _database_ _user_ _IP-address_ _IP-mask_ _auth-method_ [`_auth-options_`] hostssl _database_ _user_ _IP-address_ _IP-mask_ _auth-method_ [`_auth-options_`] hostnossl _database_ _user_ _IP-address_ _IP-mask_ _auth-method_ [`_auth-options_`] ``` 各个字段的含义如下: `local` 这条记录匹配企图通过 Unix 域套接字进行的连接。没有这种类型的记录,就不允许 Unix 域套接字的连接。 `host` 这条记录匹配企图通过 TCP/IP 进行的连接。`host`记录匹配 SSL和非SSL的连接请求。 > **Note:** 除非服务器带着合适的[listen_addresses](#calibre_link-1559)配置参数值启动, 否则将不可能进行远程的 TCP/IP 连接,因为缺省的行为是只监听本地自环地址`localhost`的连接。 `hostssl` 这条记录匹配企图使用 TCP/IP 的 SSL 连接。但必须是使用SSL加密的连接。 要使用这个选项,编译服务器的时候必须打开SSL支持。 而且在服务器启动的时候必须打开[ssl](#calibre_link-1385)配置选项(参阅[Section 17.9](#calibre_link-657))。 `hostnossl` 这条记录与`hostssl`行为相反:它只匹配那些在 TCP/IP 上不使用SSL的连接请求。 `_database_` 声明记录所匹配的数据库名称。值 `all`表明该记录匹配所有数据库, 值`sameuser`表示如果被请求的数据库和请求的用户同名,则匹配。 值`samerole`表示请求的用户必须是一个与数据库同名的角色中的成员。 (`samegroup`是一个已经废弃了,但目前仍然被接受的`samerole`同义词。) 对`samerole`来说,不认为超级用户是角色的一个成员,除非他们明确的是角色的成员, 直接的或间接的,并且不只是由于超级用户。值`replication`表示如果请求一个复制链接, 则匹配(注意复制链接不表示任何特定的数据库)。在其它情况里,这就是一个特定的 PostgreSQL数据库名字。可以通过用逗号分隔的方法声明多个数据库, 也可以通过前缀`@`来声明一个包含数据库名的文件。 `_user_` 为这条记录声明所匹配的数据库用户。值`all`表明它匹配于所有用户。否则, 它就是特定数据库用户的名字或者是一个前缀`+`的组名称。请注意, 在PostgreSQL里,用户和组没有真正的区别,`+`实际上只是意味着 "匹配任何直接或者间接属于这个角色的成员",而没有`+`记号的名字只匹配指定的角色。 为此,超级用户如果明确是角色的成员,也只算是一个角色的成员,直接的或间接的,而不只是由于超级用户。 多个用户名可以通过用逗号分隔的方法声明。一个包含用户名的文件可以通过在文件名前面前缀 `@`来声明。 `_address_` 声明这条记录匹配的客户端机器地址。这个文件可以包含主机名、IP地址范围或下面提到的特殊关键字之一。 IP 地址用标准的带有CIDR掩码长度的点分十进制声明。 掩码长度表示客户端 IP 地址必须匹配的高位二进制位数。在给出的 IP 地址里, 这个长度的右边的二进制位应该为零。在 IP 地址、`/`、 CIDR 掩码长度之间不能有空白。 典型的这种方式指定的IP地址范围举例:`172.20.143.89/32`表示一个主机, `172.20.143.0/24`表示一个小子网,`10.6.0.0/16` 表示一个大子网。`0.0.0.0/0`代表所有IPv4地址,`::/0` 代表所有IPv6地址。要声明单个主机,给 IPv4 地址声明 CIDR 掩码 32 ,给 IPv6 地址声明 128 。 不要在地址中省略结尾的 0 。 以 IPv4 格式给出的 IP 地址会匹配那些拥有对应地址的 IPv6 连接,比如`127.0.0.1` 将匹配 IPv6 地址`::ffff:127.0.0.1`。一个以 IPv6 格式给出的记录将只匹配 IPv6 连接, 即使对应的地址在 IPv4-in-IPv6 范围内。请注意如果系统的 C 库不支持 IPv6 地址, 那么 IPv6 的格式将被拒绝。 你也可以写`all`来匹配所有IP地址,`samehost` 来匹配任意服务器IP地址,或`samenet`来匹配任何服务器直接连接到的子网的任意地址。 如果指定了主机名(不是IP地址或作为潜在主机名处理的特殊关键字), 那么该名称与客户端IP地址进行反向名称解析的结果进行比较(例如,如果使用了DNS, 那么是反向DNS查找)。主机名的比较是大小写无关的。如果有一个匹配, 那么正向名称解析(例如,正向DNS查找)在主机名上执行,以检查是否有解析的地址等于客户端IP地址。 如果双向都匹配,那么这个条目被认为是匹配的。(在`pg_hba.conf` 中使用的主机名应该是客户端IP地址返回的地址到名称(address-to-name)解析的那个, 否则这行将不被匹配。某些主机名数据库允许一个IP地址关联多个主机名, 但是当要求解析一个IP地址时,操作系统将只返回一个主机名。) 主机名规范以一个点(`.`)开头,匹配一个实际主机名后缀。 所以`.example.com`将匹配`foo.example.com` (但不只是`example.com`)。 当主机名在`pg_hba.conf`中指定时,你应该确保那个名字解析是相当快的。 它将比建立一个本地名字解析缓存(如`nscd`)有优势。同样, 你可能希望启用配置参数`log_hostname`来查看客户端主机名,而不是日志中的IP地址。 有时,用户想知道为什么主机名用这个带有两个名字解析和要求反向查找IP地址的看起来复杂的方式处理, 这有时没有设置或者指向一些不受欢迎的主机名。效率是首要的:一个连接请求需要两个解析器查找当前客户端地址。 如果那个地址有解析器问题,那么就只是客户端问题。一个假想的可供选择的只做正向查找的实现, 将在每个连接请求时必须解析`pg_hba.conf`中提到的每个主机名。这样本身就是缓慢的。 并且如果有一个主机名有解析问题,那么所有主机名都会有问题。 另外,要实现后缀匹配功能必须要一个反向查找,因为实际客户端主机名需要是已知的,为了它对模式匹配。 请注意,这个行为与其他受欢迎的主机基于名称访问控制的实现是一致的,比如Apache HTTP Server 和 TCP Wrappers。 这些字段只适用于`host`,`hostssl`,`hostnossl`记录。 `_IP-address_``_IP-mask_` 这些方法可以用于作为`_CIDR-address_`表示法的替补。它不是声明掩码的长度, 而是在另外一个字段里声明实际的掩码。比如,`255.0.0.0`表示 IPv4 CIDR 掩码长度 8 , 而`255.255.255.255`表示 CIDR 掩码长度 32 。 这些字段只适用于`host`,`hostssl`,`hostnossl`记录。 `_auth-method_` 声明连接匹配这条记录的时候使用的认证方法。可能的选择在下面简介, 详细情况在[Section 19.3](#calibre_link-1259)中介绍。 `trust` 无条件地允许连接。这个方法允许任何可以与PostgreSQL 数据库服务器连接的用户以他们期望的任意PostgreSQL 数据库用户身份进行连接,而不需要口令或任何其他认证。参阅[Section 19.3.1](#calibre_link-1552)获取细节。 `reject` 无条件地拒绝连接。常用于从一个组中"过滤"某些主机,例如, 一个`拒绝`行能够从连接中锁定一个指定的主机,而稍后的行允许指定网络中的剩余的主机连接。 `md5` 要求客户端提供一个 MD5 加密的口令进行认证。参阅[Section 19.3.2](#calibre_link-1553)获取细节。 `password` 要求客户端提供一个未加密的口令进行认证。因为口令是以明文形式在网络上传递的, 所以我们不应该在不安全的网络上使用这个方式。参阅[Section 19.3.2](#calibre_link-1553)获取细节。 `gss` 使用GSSAPI认证用户。这只能用于TCP/IP连接。参阅[Section 19.3.3](#calibre_link-505)获取细节。 `sspi` 使用SSPI认证用户。这只能在Windows上使用。参阅[Section 19.3.4](#calibre_link-1554)获取细节。 `krb5` 用 Kerberos V5 认证用户。只有在进行 TCP/IP 连接的时候才能用。 参阅[Section 19.3.5](#calibre_link-504)获取细节。 `ident` 获取客户的操作系统名然后检查该用户是否匹配要求的数据库用户名, 方法是用户的身份通过与运行在客户端上的 ident 服务器连接进行判断的。 Ident认证只在进行TCP/IP连接的时候才能用。当指定本地连接时,将使用peer认证。 参阅[Section 19.3.6](#calibre_link-1555)获取细节。 `peer` 为操作系统获取客户端操作系统用户名,并检查该用户是否匹配要求的数据库用户名。 该方法只适用于本地连接。参阅[Section 19.3.7](#calibre_link-503)获取细节。 `ldap` 使用LDAP服务器进行认证。参阅[Section 19.3.8](#calibre_link-1052)获取细节。 `radius` 使用RADIUS服务器进行认证,参阅[Section 19.3.9](#calibre_link-1051)获取细节。 `cert` 使用SSL客户端证书进行认证。参阅[Section 19.3.10](#calibre_link-1391)获取细节。 `pam` 使用操作系统提供的可插入认证模块服务(PAM)来认证。参阅[Section 19.3.11](#calibre_link-1556)获取细节。 `_auth-options_` 在`_auth-method_`字段之后,字段格式可以是`_name_``=``_value_`, 指定认证方法的选项。关于哪个选项可用于哪个认证方法的详情在下面描述。 用`@`构造包含的文件是当作一列名字读取的,这些名字可以用空白或者逗号分隔。 注释用`#`引入,就像在`pg_hba.conf`里那样, 允许嵌套`@`构造。除非跟在`@`后面的文件名是一个绝对路径, 否则被当作与该文件所在目录相对的路径。 因为认证时系统是为每个连接请求顺序检查`pg_hba.conf`里的记录的, 所以这些记录的顺序是非常关键的。通常,靠前的记录有比较严的连接匹配参数和比较弱的认证方法, 而靠后的记录有比较松的匹配参数和比较严的认证方法。比如,我们一般都希望对本地 TCP/IP 连接使用 `trust`认证,而对远端的 TCP/IP 连接要求口令。在这种情况下我们将`trust` 认证方法用于来自 127.0.0.1 的连接,这条记录将出现在允许更广泛的客户端 IP 地址的使用口令认证的记录前面。 在启动和主服务器进程收到SIGHUP 信号的时候,系统都会重新装载`pg_hba.conf`文件。 如果你在活跃的系统上编辑了该文件,就必须通知主服务器(使用`pg_ctl reload` 或`kill -HUP`)重新加载该文件。 > **Tip:** 一个用户要想成功连接到特定的数据库,不仅需要通过`pg_hba.conf`的检查, 还必须要有该数据库上的`CONNECT`权限。如果希望限制哪些用户能够连接到哪些数据库, 赋予/撤销`CONNECT`权限通常比在`pg_hba.conf`中设置规则简单。 [Example 19-1](#calibre_link-1560)里是`pg_hba.conf`记录的一些例子。 阅读下文理解不同认证方法的细节。 **Example 19-1\. `pg_hba.conf`记录的例子** ``` # 允许在本机上的任何用户使用 Unix 域套接字(本地连接的缺省) # 以任何数据库用户身份连接任何数据库 # # TYPE DATABASE USER ADDRESS METHOD local all all trust # 和上面相同,但是使用的是回环的(loopback)TCP/IP 连接 # # TYPE DATABASE USER ADDRESS METHOD host all all 127.0.0.1/32 trust # 和上面一行相同,但是用的是独立的子网掩码字段 # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host all all 127.0.0.1 255.255.255.255 trust # 在IPv6上相同。 # # TYPE DATABASE USER ADDRESS METHOD host all all ::1/128 trust # 和上面相同,但是使用一个主机名(通常包括IPv4 和 IPv6)。 # # TYPE DATABASE USER ADDRESS METHOD host all all localhost trust # 允许 IP 地址为 192.168.93.x 的任何主机与 "postgres" 数据库相连, # 用与他们在自己的主机上相同 ident 的用户名标识他自己(通常是他的操作系统用户名) # # TYPE DATABASE USER ADDRESS METHOD host postgres all 192.168.93.0/24 ident # 允许来自主机 192.168.12.10 的用户提供了正确的口令之后与 "postgres" 数据库连接。 # # TYPE DATABASE USER ADDRESS METHOD host postgres all 192.168.12.10/32 md5 # 允许来自在example.com域里的主机的用户在提供了正确的口令之后与任意数据库连接。 # # TYPE DATABASE USER ADDRESS METHOD host all all .example.com md5 # 如果前面没有其它 "host" 行,那么下面两行将拒绝所有来自 192.168.54.1 的连接请求(因为前面的记录先匹配)。 # 但是允许来自互联网上其它任何地方的有效的 Kerberos 5 认证的连接。 # 零掩码引起不考虑主机 IP 的任何位。因此它匹配任何主机。 # # TYPE DATABASE USER 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 ADDRESS METHOD host all all 192.168.0.0/16 ident map=omicron # 如果下面是用于本地连接的仅有的三行,那么它们将允许本地用户只和同名数据库连接。 # 只有管理员和 "support" 角色里的成员例外,他们可以连接到任何数据库。 # $PGDATA/admins 文件列出了那些允许与所有数据库连接的用户名。 # 在所有情况下都需要口令。 # # TYPE DATABASE USER 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 ```