当使用 Ident 或 GSSAPI 之类的外部认证系统时,发起连接的操作系统用户名可能不同于要使用的数据库用户(角色)。在这种情况下,可以通过用户名映射把操作系统用户名映射为数据库用户。要使用用户名映射,需要在 pg_hba.conf 的选项字段中指定 map=map-name。此选项适用于所有会接收外部用户名的认证方法。由于不同连接可能需要不同映射,在 pg_hba.conf 中通过 map-name 参数指定要使用的映射,以表明每个连接应使用哪个映射。
用户名映射在 ident 映射文件中定义。该文件默认名为 pg_ident.conf,存储在集簇的数据目录中。(也可以将映射文件放在其他位置;参见 ident_file 配置参数。)ident 映射文件中各行的基本格式如下:
map-namesystem-usernamedatabase-username
注释和空白的处理方式与 pg_hba.conf 相同。map-name 是任意名称,用于在 pg_hba.conf 中引用此映射。另两个字段指定操作系统用户名及与之匹配的数据库用户名。同一个 map-name 可以重复使用,以便在一项映射中指定多个用户对应关系。
一个操作系统用户可以对应多少个数据库用户,没有限制,反之亦然。因此,映射中的条目应理解为“此操作系统用户可以作为此数据库用户连接”,而不是说二者等同。只要存在一个映射条目,将从外部认证系统取得的用户名与用户请求连接时使用的数据库用户名配对,就会允许该连接。
如果 system-username 字段以斜杠(/)开头,该字段的其余部分就会被视为正则表达式。(参见 Section 9.7.3.1,其中介绍了 PostgreSQL 的正则表达式语法。)正则表达式可以包含一个捕获,即用圆括号括起来的子表达式。系统用户名中与捕获匹配的部分,可以在 database-username 字段中使用 \1(反斜杠加数字一)来引用。这样就可以在一行中映射多个用户名,对简单的语法替换尤其有用。例如,以下条目
mymap /^(.*)@mydomain\.com$ \1 mymap /^(.*)@otherdomain\.com$ guest
会去掉系统用户名中的域名部分(如果用户名以 @mydomain.com 结尾),并允许系统用户名以 @otherdomain.com 结尾的任何用户登录为 guest。
记住在默认情况下,一个正则表达式可以只匹配字符串的一部分。如上例所示,使用^和$来强制匹配整个系统用户名通常是明智的。
在启动时以及主服务器进程收到 SIGHUP 信号时,pg_ident.conf 文件会被读取。 如果你在运行中的系统上编辑了该文件,就需要通知 postmaster(使用 pg_ctl reload、调用 SQL 函数 pg_reload_conf(),或者使用 kill -HUP)重新读取该文件。
Example 20.2 展示了一个可与 Example 20.1 中的 pg_hba.conf 文件配合使用的 pg_ident.conf 文件。在这个示例中,任何登录到 192.168 网络中某台机器上的用户,如果其操作系统用户名不是 bryanh、ann 或 robert,都不会被授予访问权限。Unix 用户 robert 只有在尝试以 PostgreSQL 用户 bob 身份连接时才被允许访问,而不能以 robert 或其他身份连接。ann 只能以 ann 身份连接。用户 bryanh 则可以以 bryanh 或 guest1 身份连接。
Example 20.2. 示例 pg_ident.conf 文件
# MAPNAME SYSTEM-USERNAME PG-USERNAME omicron bryanh bryanh omicron ann ann # bob 在这些机器上有用户名 robert omicron robert bob # bryanh 也可以作为 guest1 连接 omicron bryanh guest1