选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.5 已于 2021 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

19.3. 认证方法 #

下面几节会更详细地介绍这些认证方法。

19.3.1. 信任认证 #

trust认证被指定时,PostgreSQL假设任何可以连接到服务器的人都被授权使用他们指定的任何数据库用户名(即使是超级用户)访问数据库。当然,在databaseuser列中设置的限制仍然适用。只有当在操作系统层对进入服务器的连接有足够保护时,才应该使用这种方法。

trust认证对于单用户工作站的本地连接是非常合适和方便的。通常它本身适用于一台多用户机器。不过,只要你利用文件系统权限限制了对服务器的 Unix 域套接字文件的访问,即使在多用户机器上,你也可能可以使用trust。 要做这些限制,你可以设置第 18.3 节中描述的unix_socket_permissions配置参数(可能还有unix_socket_group)。 或者你可以设置unix_socket_directories配置参数来把 Unix 域套接字文件放在一个经过恰当限制的目录中。

设置文件系统权限只能有助于 Unix 套接字连接。本地 TCP/IP 连接不会被文件系统权限限制。因此,如果你想利用文件系统权限来控制本地安全,那么从pg_hba.conf中移除host ... 127.0.0.1 ...行,或者把它改为一个非trust认证方法。

只有当你信任由 pg_hba.conf 中指定 trust 的行所允许连接的每台机器上的每个用户时,trust 认证才适合用于 TCP/IP 连接。对来自 localhost(127.0.0.1)以外的任何 TCP/IP 连接使用 trust,通常都不合理。

19.3.2. 密码认证 #

基于密码的认证方法有 md5password。除了密码通过连接发送的方式——前者以 MD5 哈希发送、后者以明文发送——之外,这两种方法的操作是相似的。

如果你担心密码嗅探攻击,那么应优先使用 md5。 如果可能,应始终避免使用明文 password。 不过,md5 不能与db_user_namespace功能一起使用。如果连接被 SSL 加密保护着,那么可以安全地使用 password(不过如果依靠 SSL,SSL 证书认证可能是更好的选择)。

PostgreSQL 数据库密码独立于操作系统用户密码。每个数据库用户的密码存储在 pg_authid 系统目录中。可以使用 SQL 命令 CREATE USERALTER ROLE 管理密码,例如 CREATE USER foo WITH PASSWORD 'secret',如果未为某个用户设置密码,存储的密码就是空值,该用户的密码认证始终会失败。

19.3.3. GSSAPI 认证 #

GSSAPI 是 RFC 2743 定义的安全认证行业标准协议。PostgreSQL 按照 RFC 1964 支持使用 Kerberos 认证的 GSSAPIGSSAPI 为支持它的系统提供自动认证(单点登录)。认证过程本身是安全的,但除非使用 SSL,否则数据库连接上传输的数据不会加密。

当编译PostgreSQL时,GSSAPI 支持必须被启用,详见第 15 章

GSSAPI 使用 Kerberos 时,采用格式为 servicename/hostname@realm 的标准主体。PostgreSQL 服务器会接受其所用 keytab 中包含的任何主体,但客户端建立连接时,必须注意通过 krbsrvname 连接参数指定正确的主体信息。(另见 第 31.1.2 节。)构建时可以使用 ./configure --with-krb-srvnam=whatever,将安装默认值从 postgres 改为其他值。在大多数环境中,无需更改此参数。某些 Kerberos 实现可能要求不同的服务名,例如 Microsoft Active Directory 要求服务名使用大写(POSTGRES)。

hostname 是服务器机器的完全限定主机名。服务主体的 realm 是服务器机器的首选 realm。

可以通过 pg_ident.conf 将客户端主体映射到不同的 PostgreSQL 数据库用户名。例如,可以将 pgusername@realm 映射为 pgusername。也可以不使用任何映射,直接将完整的 username@realm 主体用作 PostgreSQL 中的角色名。

PostgreSQL 还支持一个从主体中去掉 realm 的参数。提供这种方法是为了向后兼容,强烈不建议使用,因为这样就无法区分来自不同 realm 但用户名相同的用户。要启用此行为,将 include_realm 设为 0。对于简单的单 realm 安装环境,将 include_realmkrb_realm 参数结合使用(它会检查所提供的 realm 是否与 krb_realm 参数中的值完全一致),这种做法仍是安全的;但与在 pg_ident.conf 中指定显式映射相比,它的能力较弱。

确保 PostgreSQL 服务器账户能够读取服务器的 keytab 文件(最好仅可读取)。(另见 第 17.1 节。)密钥文件的位置由 krb_server_keyfile 配置参数指定。默认位置是 /usr/local/pgsql/etc/krb5.keytab(或者构建时用 sysconfdir 指定的目录)。出于安全考虑,建议为 PostgreSQL 服务器使用专用 keytab,而不是放宽系统 keytab 文件的权限。

keytab 文件由 Kerberos 软件生成;详情参见 Kerberos 文档。以下示例适用于兼容 MIT 的 Kerberos 5 实现:

kadmin% ank -randkey postgres/server.my.domain.org
kadmin% ktadd -k krb5.keytab postgres/server.my.domain.org

连接数据库时,请确保持有与请求的数据库用户名相匹配的主体票据。例如,数据库用户名为 fred 时,主体 fred@EXAMPLE.COM 可以连接。如果还要允许主体 fred/users.example.com@EXAMPLE.COM,请按 第 19.2 节 所述使用用户名映射。

以下配置选项适用于 GSSAPI

include_realm

如果设为 0,则在通过用户名映射(第 19.2 节)之前,会先从已认证用户的主体名中去掉 realm 名称。 不建议这样做;它主要是为了向后兼容而保留的,因为在多 realm 环境中这并不安全,除非同时使用了 krb_realm。 建议将 include_realm 保持为默认值(1),并在 pg_ident.conf 中提供显式映射。

map

允许在系统用户名与数据库用户名之间建立映射。详见 第 19.2 节。对于 username@EXAMPLE.COM(或较少见的 username/hostbased@EXAMPLE.COM)这样的 GSSAPI/Kerberos 主体,映射所用的用户名是 username@EXAMPLE.COM(或相应的 username/hostbased@EXAMPLE.COM),除非将 include_realm 设为 0,此时映射所见的系统用户名为 username(或 username/hostbased)。

krb_realm

设置用于匹配用户主体名的 realm。如果设置了该参数,则只接受来自该 realm 的用户;如果未设置,则允许来自任意 realm 的用户连接,但仍受已执行的用户名映射约束。

19.3.4. SSPI 认证 #

SSPI 是一种提供安全认证和单点登录的 Windows 技术。PostgreSQL 会以 negotiate 模式使用 SSPI,尽可能使用 Kerberos,否则自动回退到 NTLM。只有服务器和客户端都运行 Windows,或者在非 Windows 平台上可用 GSSAPI 时,SSPI 认证才能工作。

当使用Kerberos认证时,SSPIGSSAPI的工作方式相同,详见第 19.3.3 节

SSPI 支持下列配置选项:

include_realm

如果设为 0,则在通过用户名映射(第 19.2 节)之前,会先从已认证用户的主体名中去掉 realm 名称。 不建议这样做;它主要是为了向后兼容而保留的,因为在多 realm 环境中这并不安全,除非同时使用了 krb_realm。 建议将 include_realm 保持为默认值(1),并在 pg_ident.conf 中提供显式映射。

map

允许在系统用户名与数据库用户名之间建立映射。详见 第 19.2 节。对于 SSPI/Kerberos 主体,例如 username@EXAMPLE.COM(或者较少见的 username/hostbased@EXAMPLE.COM),用于映射的用户名分别是 username@EXAMPLE.COM(或 username/hostbased@EXAMPLE.COM),除非已经将 include_realm 设为 0;在那种情况下,映射时视为系统用户名的是 username(或 username/hostbased)。

krb_realm

设置用于匹配用户主体名的 realm。如果设置了该参数,则只接受来自该 realm 的用户;如果未设置,则允许来自任意 realm 的用户连接,但仍受已执行的用户名映射约束。

19.3.5. Ident 认证 #

ident 认证方法通过从一个 ident 服务器获得客户端的操作系统用户名并且用它作为被允许的数据库用户名(和可选的用户名映射)来工作。它只在 TCP/IP 连接上支持。

注意

当为一个本地(非 TCP/IP)连接指定 ident 时,将实际使用 peer 认证(见第 19.3.6 节)。

以下配置选项适用于 ident

map

允许在系统用户名和数据库用户名之间进行映射。详见 第 19.2 节

标识协议在 RFC 1413 中定义。几乎所有类 Unix 操作系统都自带 ident 服务器,默认监听 TCP 端口 113。ident 服务器的基本功能是回答这样的问题:从你的端口 X 连到我的端口 Y 的连接,是哪个用户发起的?由于建立物理连接时,PostgreSQL 已知 XY,因此可以询问连接客户端所在主机上的 ident 服务器,理论上能够确定任意给定连接的操作系统用户。

这个过程的缺点在于它依赖客户端本身的可信性:如果客户端机器不可信或者已被攻破,攻击者几乎可以在 113 端口上运行任何程序,并返回任意他选择的用户名。因此,这种认证方法只适用于封闭网络,在这类网络中每台客户端机器都受到严格控制,而且数据库管理员与系统管理员之间保持密切协作。换句话说,你必须信任运行 ident 服务器的那台机器。请注意下面的警告:

 

标识协议的本意不是作为一种授权或访问控制协议。

 
  --RFC 1413

有些 ident 服务器提供了一个非标准选项,会让返回的用户名被加密,而解密所需密钥只有发起连接机器的管理员才知道。将 ident 服务器与 PostgreSQL 配合使用时,绝不能启用这个选项,因为 PostgreSQL 无法解密返回的字符串,也就无法确定实际用户名。

19.3.6. Peer 认证 #

Peer 认证通过从内核获取客户端的操作系统用户名,并把它用作被允许的数据库用户名(可结合可选的用户名映射)来工作。这种方法只支持本地连接。

以下配置选项适用于 peer

map

允许在系统用户名和数据库用户名之间进行映射。详见 第 19.2 节

Peer 认证只在提供 getpeereid() 函数、SO_PEERCRED 套接字参数或类似机制的操作系统上可用。目前这包括 Linux、大多数 BSD 变种(包括 OS X)以及 Solaris

19.3.7. LDAP 认证 #

这种认证方法的工作方式与 password 类似,只不过它使用 LDAP 作为密码验证方法。LDAP 只用于验证用户名/密码对。因此,在使用 LDAP 进行认证之前,用户必须已经存在于数据库中。

LDAP 认证可以在两种模式下工作。第一种模式称为简单绑定模式,服务器会绑定到按 prefix username suffix 形式构造出的可分辨名称。通常,prefix 参数用于指定 cn=,或在 Active Directory 环境中指定 DOMAIN\suffix 则用于指定非 Active Directory 环境中 DN 的剩余部分。

第二种模式称为搜索+绑定模式,服务器首先使用由 ldapbinddnldapbindpasswd 指定的固定用户名和密码绑定到 LDAP 目录,并搜索试图登录数据库的用户。如果没有配置用户名和密码,则会尝试对目录进行匿名绑定。搜索会在 ldapbasedn 指定的子树上进行,并尝试对 ldapsearchattribute 指定的属性做精确匹配。一旦在搜索中找到了该用户,服务器会断开连接,再作为该用户重新绑定到目录,并使用客户端指定的密码来验证登录是否正确。这种模式与 Apache mod_authnz_ldappam_ldap 等软件中的 LDAP 认证方案相同。这种方法使目录中用户对象的位置更具灵活性,但会与 LDAP 服务器建立两个独立的连接。

以下配置选项适用于两种模式:

ldapserver

要连接的LDAP服务器的名称或IP地址。可以指定多个服务器,用空格分隔。

ldapport

要连接的LDAP服务器的端口号。如果未指定端口,则将使用LDAP库的默认端口设置。

ldaptls

设为 1 时,PostgreSQL 与 LDAP 服务器之间的连接会使用 TLS 加密。注意,这只加密与 LDAP 服务器之间的流量 — 除非使用 SSL,否则与客户端之间的连接仍不加密。

以下选项仅适用于简单绑定模式:

ldapprefix

在进行简单绑定认证时,附加到用户名前面以形成绑定 DN 的字符串。

ldapsuffix

在进行简单绑定认证时,附加到用户名后面以形成绑定 DN 的字符串。

以下选项仅适用于搜索加绑定模式:

ldapbasedn

在进行搜索+绑定认证时,用作用户搜索起点的根 DN。

ldapbinddn

在进行搜索+绑定认证时,用于绑定到目录并执行搜索的用户 DN。

ldapbindpasswd

在进行搜索+绑定认证时,用于绑定到目录并执行搜索的用户密码。

ldapsearchattribute

在进行搜索+绑定认证时,用于与用户名匹配的属性。如果未指定属性,则会使用 uid 属性。

ldapurl

符合 RFC 4516 的 LDAP URL。这是另一种指定部分 LDAP 选项的方式,写法更紧凑、更标准。其格式为

ldap://host[:port]/basedn[?[attribute][?[scope]]]

scope 必须是以下值之一:baseonesub,通常使用最后一个。只会使用一个属性,而且不支持标准 LDAP URL 的其他某些组件,例如过滤器和扩展。

对于非匿名绑定,必须将ldapbinddnldapbindpasswd指定为单独的选项。

要使用加密的 LDAP 连接,除了 ldapurl,还必须使用 ldaptls 选项。不支持 ldaps URL 方案(直接 SSL 连接)。

目前只有 OpenLDAP 支持 LDAP URL,Windows 不支持。

将简单绑定模式的配置选项与搜索+绑定模式的配置选项混用是错误的。

下面是一个简单绑定 LDAP 配置示例:

host ... ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"

当请求以数据库用户 someuser 连接数据库服务器时,PostgreSQL 将尝试使用 DN cn=someuser, dc=example, dc=net 和客户端提供的密码绑定到 LDAP 服务器。如果该连接成功,数据库访问就会被授予。

下面是搜索加绑定配置的示例:

host ... ldap ldapserver=ldap.example.net ldapbasedn="dc=example, dc=net" ldapsearchattribute=uid

当请求以数据库用户 someuser 的身份连接数据库服务器时,PostgreSQL 会尝试匿名绑定到 LDAP 服务器(因为没有指定 ldapbinddn),并在指定的基础 DN 下搜索 (uid=someuser)。如果找到了条目,就会尝试使用找到的信息和客户端提供的密码进行绑定。如果第二次连接成功,就会授予数据库访问权限。

下面是以 URL 形式写出的同一个搜索+绑定配置:

host ... ldap ldapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub"

某些支持 LDAP 认证的其他软件也使用相同的 URL 格式,因此共享这类配置会更容易。

提示

如示例中所示,由于 LDAP 通常使用逗号和空格来分割一个 DN 的不同部分,在配置 LDAP 选项时通常有必要使用双引号包围的参数值。

19.3.8. RADIUS 认证 #

这种认证方法的工作方式与 password 类似,只不过它使用 RADIUS 作为密码验证方式。RADIUS 只用于验证用户名/密码对。因此,在使用 RADIUS 进行认证之前,用户必须已经存在于数据库中。

使用 RADIUS 认证时,会向配置好的 RADIUS 服务器发送一条 Access Request 消息。 该请求的类型为 Authenticate Only,并包含 user namepassword(加密的)以及 NAS Identifier 参数。 该请求会使用与服务器共享的密钥进行加密。 这台服务器会返回 Access AcceptAccess Reject 作为响应。PostgreSQL 不支持 RADIUS 记账。

RADIUS 支持下列配置选项:

radiusserver

要连接的 RADIUS 服务器的名称或 IP 地址。此参数为必需项。

radiussecret

与 RADIUS 服务器进行安全通信时使用的共享密钥。它在 PostgreSQL 服务器和 RADIUS 服务器上必须完全相同。建议它至少是一个 16 个字符长的字符串。此参数为必需项。

注意

只有当 PostgreSQL 在构建时启用了 OpenSSL 支持,所使用的加密向量才具有足够的密码学强度。在其他情况下,到 RADIUS 服务器的传输只能被视为经过混淆,而非受到安全保护;如有必要,应额外采取外部安全措施。

radiusport

要连接的 RADIUS 服务器端口号。如果未指定端口,则会使用默认端口 1812

radiusidentifier

在 RADIUS 请求中用作 NAS Identifier 的字符串。这个参数可用作第二个参数,例如标识用户正尝试以哪个数据库用户进行认证,从而便于在 RADIUS 服务器上进行策略匹配。如果未指定标识符,则默认使用 postgresql

19.3.9. 证书认证 #

这种认证方法使用 SSL 客户端证书进行认证,因此仅适用于 SSL 连接。使用此方法时,服务器要求客户端提供有效的证书,不会向客户端发送密码提示。服务器会将证书的 cn(通用名称)属性与请求的数据库用户名比较,匹配时才允许登录。可以使用用户名映射,允许 cn 与数据库用户名不同。

SSL 证书认证支持下列配置选项:

map

允许在系统用户名和数据库用户名之间进行映射。详见 第 19.2 节

19.3.10. PAM 认证 #

这种认证方法与 password 类似,只是使用 PAM(可插拔认证模块)作为认证机制。默认的 PAM 服务名为 postgresql。PAM 仅用于验证用户名与密码的组合。因此,必须先在数据库中创建该用户,才能使用 PAM 进行认证。有关 PAM 的更多信息,参见 Linux-PAM 页面

PAM 支持下列配置选项:

pamservice

PAM 服务名称。

注意

如果 PAM 被设置为读取 /etc/shadow,认证将会失败,因为 PostgreSQL 服务器是由非 root 用户启动的。不过,当 PAM 被配置为使用 LDAP 或其他认证方法时,这就不是问题。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。