19.3. Authentication methods #
下面几节会更详细地介绍这些认证方法。
19.3.1. trust 认证 #
当trust认证被指定时,PostgreSQL假设任何可以连接到服务器的人都被授权使用他们指定的任何数据库用户名(即使是超级用户)访问数据库。当然,在database和 user列中设置的限制仍然适用。只有当在操作系统层对进入服务器的连接有足够保护时,才应该使用这种方法。
trust 认证对单用户工作站上的本地连接来说是合适且非常方便的。在多用户机器上,通常单用它并不合适。不过,如果用文件系统权限限制对服务器 Unix 域套接字文件的访问,即使在多用户机器上也可以使用
trust。为此,可按第 18.3 节中的说明设置
unix_socket_permissions(可能还有
unix_socket_group)配置参数。或者,也可以设置 unix_socket_directory
配置参数,把套接字文件放在一个经过适当限制的目录中。
设置文件系统权限只能有助于 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. 密码认证 #
基于密码的认证方法有 md5 和 password。除了密码通过连接发送的方式——前者以 MD5 哈希发送、后者以明文发送——之外,这两种方法的操作是相似的。
如果你担心密码“嗅探”攻击,那么应优先使用 md5。如果可能,应始终避免使用明文 password。不过,md5 不能与db_user_namespace功能一起使用。如果连接被 SSL 加密保护着,那么可以安全地使用 password(不过如果依靠 SSL,SSL 证书认证可能是更好的选择)。
PostgreSQL 数据库密码与操作系统用户密码是分开的。每个数据库用户的密码存储在
pg_authid 系统目录中。密码可以用 SQL 命令CREATE USER和ALTER USER管理,例如
CREATE USER foo WITH PASSWORD 'secret'。如果用户没有设置密码,存储的密码为空,该用户的密码认证将始终失败。
19.3.3. GSSAPI 认证 #
GSSAPI 是 RFC 2743 定义的安全认证行业标准协议。PostgreSQL 按照 RFC 1964 支持使用 Kerberos 认证的 GSSAPI。GSSAPI 为支持它的系统提供自动认证(单点登录)。认证过程本身是安全的,但除非使用 SSL,否则数据库连接上传输的数据不会加密。
当 GSSAPI 使用
Kerberos 时,它使用格式为
的标准主体。关于主体各部分的说明以及如何设置所需的密钥,参见第 19.3.5 节。
servicename/hostname@realm
当编译PostgreSQL时,GSSAPI 支持必须被启用,详见第 15 章。
GSSAPI 支持以下配置选项:
include_realm如果设为
1,已认证用户主体中的 realm 名会包含在通过用户名映射(第 19.2 节)传递的系统用户名中。这是推荐的配置,否则无法区分来自不同 realm 的同名用户。此参数的默认值为 0(表示不在系统用户名中包含 realm),但在 PostgreSQL 的未来版本中可能改为 1。用户可以显式设置它,以避免升级时出现任何问题。map允许在系统用户名与数据库用户名之间进行映射。详见第 19.2 节。对于 GSSAPI/Kerberos 主体,例如
username@EXAMPLE.COM(或较少见的username/hostbased@EXAMPLE.COM),用于映射的默认用户名是username(或分别为username/hostbased),除非include_realm已设为 1(如上文建议的那样),此时映射时看到的系统用户名是username@EXAMPLE.COM(或username/hostbased@EXAMPLE.COM)。krb_realm设置匹配用户主体名的 realm。如果设置了此参数,将只接受该 realm 的用户。如果未设置,任何 realm 的用户都可以连接,但须完成相应的用户名映射。
19.3.4. SSPI authentication #
SSPI 是一种用于单点登录安全认证的
Windows 技术。PostgreSQL 将以
negotiate 模式使用 SSPI,该模式在可能时使用
Kerberos,在其他情况下自动回退到
NTLM。SSPI 认证只在服务器和客户端都运行
Windows 时才起作用。
当使用Kerberos认证时,SSPI和GSSAPI的工作方式相同,详见第 19.3.3 节。
SSPI 支持以下配置选项:
include_realm如果设为
1,已认证用户主体中的 realm 名会包含在通过用户名映射(第 19.2 节)传递的系统用户名中。这是推荐的配置,否则无法区分来自不同 realm 的同名用户。此参数的默认值为 0(表示不在系统用户名中包含 realm),但在 PostgreSQL 的未来版本中可能改为 1。用户可以显式设置它,以避免升级时出现任何问题。map允许在系统用户名与数据库用户名之间进行映射。详见第 19.2 节。对于 SSPI/Kerberos 主体,例如
username@EXAMPLE.COM(或较少见的username/hostbased@EXAMPLE.COM),用于映射的默认用户名是username(或分别为username/hostbased),除非include_realm已设为 1(如上文建议的那样),此时映射时看到的系统用户名是username@EXAMPLE.COM(或username/hostbased@EXAMPLE.COM)。krb_realm设置匹配用户主体名的 realm。如果设置了此参数,将只接受该 realm 的用户。如果未设置,任何 realm 的用户都可以连接,但须完成相应的用户名映射。
19.3.5. Kerberos authentication #
注意
原生 Kerberos 认证已被弃用,只应用于向后兼容。鼓励新的和升级的安装改用行业标准的 GSSAPI 认证方法(参见第 19.3.3 节)。
Kerberos 是一种行业标准的、适合在公共网络上进行分布式计算的安全认证系统。Kerberos 系统的说明超出了本文档的范围;在最一般的形式下它可能相当复杂(但功能强大)。Kerberos FAQ 或 MIT Kerberos 页面是不错的入门起点。Kerberos 发行版有多个来源。Kerberos 提供安全认证,但不加密在网络上传递的查询或数据;为此请使用 SSL。
PostgreSQL 支持 Kerberos 版本 5。构建 PostgreSQL 时必须启用 Kerberos 支持;更多信息参见第 15 章。
PostgreSQL 的运行方式与普通的 Kerberos 服务相同。服务主体的名称为
。
servicename/hostname@realm
servicename 可以在服务器端用krb_srvname配置参数设置,在客户端用
krbsrvname 连接参数设置。(另见第 31.1 节。)安装默认值可以在构建时用
./configure --with-krb-srvnam=whatever
从默认的 postgres 改为其他值。在大多数环境中,此参数永远不需要更改。但是,在同一台主机上支持多个
PostgreSQL 安装时,就需要修改它。某些 Kerberos
实现可能还要求不同的服务名,例如
Microsoft Active Directory 要求服务名为大写(POSTGRES)。
hostname 是服务器机器的完全限定主机名。服务主体的 realm 是服务器机器的首选 realm。
客户端主体的第一个组成部分必须是 PostgreSQL 数据库用户名,例如 pgusername@realm。或者,也可以使用用户名映射,将主体名的第一个组成部分映射为数据库用户名。默认情况下,PostgreSQL 不检查客户端的 realm。如果启用了跨 realm 认证并且需要验证 realm,请使用 krb_realm 参数,或者启用 include_realm 并使用用户名映射来检查 realm。
确保你的服务器 keytab 文件可被
PostgreSQL 服务器账户读取(最好只有该账户可读)。(另见第 17.1 节。)密钥文件的位置由krb_server_keyfile配置参数指定。默认值为
/usr/local/pgsql/etc/krb5.keytab(或构建时指定为
sysconfdir 的任何目录)。
keytab 文件由 Kerberos 软件生成;详情参见 Kerberos 文档。以下示例适用于兼容 MIT 的 Kerberos 5 实现:
kadmin%ank -randkey postgres/server.my.domain.orgkadmin%ktadd -k krb5.keytab postgres/server.my.domain.org
连接数据库时,请确保持有与请求的数据库用户名相匹配的主体票据。例如,数据库用户名为 fred 时,主体 fred@EXAMPLE.COM 可以连接。如果还要允许主体 fred/users.example.com@EXAMPLE.COM,请按第 19.2 节所述使用用户名映射。
如果在
Apache Web 服务器上使用 mod_auth_kerb和
mod_perl,则可以在
mod_perl 脚本中使用
AuthType KerberosV5SaveCredentials。这样即可通过 Web 安全地访问数据库,无需额外的密码。
Kerberos 支持以下配置选项:
map允许在系统用户名与数据库用户名之间进行映射。详见第 19.2 节。
include_realm如果设为
1,已认证用户主体中的 realm 名会包含在通过用户名映射(第 19.2 节)传递的系统用户名中。这有助于处理来自多个 realm 的用户。krb_realm设置匹配用户主体名的 realm。如果设置了此参数,将只接受该 realm 的用户。如果未设置,任何 realm 的用户都可以连接,但须完成相应的用户名映射。
krb_server_hostname设置服务主体的主机名部分。它与
krb_srvname组合生成完整的服务主体,即krb_srvname/krb_server_hostname@REALM。如果未设置,默认值为服务器主机名。
19.3.6. 基于 ident 的认证 #
ident 认证方法的工作方式是获取客户端的操作系统用户名,并把它用作允许的数据库用户名(可选进行用户名映射)。确定客户端用户名是安全上的关键点,其工作方式因连接类型而异,如下所述。
以下配置选项适用于 ident:
map允许在系统用户名和数据库用户名之间进行映射。详见第 19.2 节。
19.3.6.1. 通过 TCP/IP 的 Ident 认证
“标识协议”在 RFC 1413 中定义。几乎所有类 Unix 操作系统都自带 ident 服务器,默认监听 TCP 端口 113。ident 服务器的基本功能是回答这样的问题:“从你的端口 X 连到我的端口 Y 的连接,是哪个用户发起的?”由于建立物理连接时,PostgreSQL 已知 X 和 Y,因此可以询问连接客户端所在主机上的 ident 服务器,理论上能够确定任意给定连接的操作系统用户。
这个过程的缺点在于它依赖客户端本身的可信性:如果客户端机器不可信或者已被攻破,攻击者几乎可以在 113 端口上运行任何程序,并返回任意他选择的用户名。因此,这种认证方法只适用于封闭网络,在这类网络中每台客户端机器都受到严格控制,而且数据库管理员与系统管理员之间保持密切协作。换句话说,你必须信任运行 ident 服务器的那台机器。请注意下面的警告:
标识协议的本意不是作为一种授权或访问控制协议。 | ||
| --RFC 1413 | ||
有些 ident 服务器提供了一个非标准选项,会让返回的用户名被加密,而解密所需密钥只有发起连接机器的管理员才知道。将 ident 服务器与 PostgreSQL 配合使用时,绝不能启用这个选项,因为 PostgreSQL 无法解密返回的字符串,也就无法确定实际用户名。
19.3.6.2. 通过本地套接字的 Ident 认证
在支持对 Unix 域套接字使用
SO_PEERCRED 请求的系统(目前包括
Linux、FreeBSD、NetBSD、OpenBSD、BSD/OS 和
Solaris)上,ident 认证也可以应用于本地连接。PostgreSQL 使用 SO_PEERCRED 查明所连接客户端进程的操作系统名称。在这种情况下,使用 ident
认证不会增加任何安全风险;事实上,在这类系统上,它是本地连接的首选方案。
在不支持
SO_PEERCRED 请求的系统上,ident 认证只适用于 TCP/IP 连接。作为一种变通办法,可以指定
localhost 地址
127.0.0.1 并连接到该地址。此方法的可信程度取决于你对本地 ident 服务器的信任程度。
19.3.7. LDAP 认证 #
这种认证方法的工作方式与 password 类似,只不过它使用 LDAP 作为密码验证方法。LDAP 只用于验证用户名/密码对。因此,在使用 LDAP 进行认证之前,用户必须已经存在于数据库中。
LDAP 认证可以在两种模式下运作。在第一种模式下,服务器将绑定到由
prefix username suffix
构造的可分辨名称。通常,prefix 参数用于指定
cn=,或在 Active Directory 环境中指定
DOMAIN\。suffix 用于在非 Active Directory 环境中指定 DN 的其余部分。
在第二种模式下,服务器首先以固定的用户名和密码(由
ldapbinddn 和
ldapbindpasswd 指定)绑定到 LDAP
目录,并搜索尝试登录数据库的用户。如果未配置用户和密码,将尝试匿名绑定到目录。搜索将在
ldapbasedn 下的子树上进行,并尝试与
ldapsearchattribute 中指定的属性精确匹配。如果未指定属性,将使用
uid 属性。一旦在搜索中找到该用户,服务器就会断开连接,并以该用户身份、用客户端指定的密码重新绑定到目录,以验证登录是否正确。这种方法在用户对象位于目录中何处这一问题上提供了大得多的灵活性,但会导致与 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在进行搜索+绑定认证时,搜索中与用户名匹配的属性。
注意
由于 LDAP 常用逗号和空格分隔 DN 的不同部分,在配置 LDAP 选项时常常需要使用双引号括住的参数值,例如:
ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"
19.3.8. RADIUS 认证 #
这种认证方法的工作方式与 password 类似,只不过它使用 RADIUS 作为密码验证方式。RADIUS 只用于验证用户名/密码对。因此,在使用 RADIUS 进行认证之前,用户必须已经存在于数据库中。
使用 RADIUS 认证时,会向配置好的 RADIUS 服务器发送一条 Access Request 消息。该请求的类型为 Authenticate Only,并包含 user name、password(加密的)以及 NAS Identifier 参数。该请求会使用与服务器共享的密钥进行加密。这台服务器会返回 Access Accept 或 Access 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. Certificate authentication #
这种认证方法使用 SSL 客户端证书进行认证,因此仅适用于 SSL 连接。使用此方法时,服务器要求客户端提供有效的证书,不会向客户端发送密码提示。服务器会将证书的 cn(通用名称)属性与请求的数据库用户名比较,匹配时才允许登录。可以使用用户名映射,允许 cn 与数据库用户名不同。
SSL 证书认证支持下列配置选项:
map允许在系统用户名和数据库用户名之间进行映射。详见第 19.2 节。
19.3.10. PAM authentication #
这种认证方法的工作方式与
password 类似,只不过它使用 PAM(可插拔认证模块)作为认证机制。默认的 PAM 服务名为
postgresql。PAM 只用于验证用户名/密码对。因此,在使用 PAM 进行认证之前,用户必须已经存在于数据库中。关于 PAM 的更多信息,请阅读
Linux-PAM 页面和
Solaris PAM 页面。
PAM 支持下列配置选项:
pamservicePAM 服务名称。
注意
如果 PAM 被设置为读取 /etc/shadow,认证将会失败,因为 PostgreSQL 服务器是由非 root 用户启动的。不过,当 PAM 被配置为使用 LDAP 或其他认证方法时,这就不是问题。