19.3. 认证方法

下列小节更详细地描述认证方法。

19.3.1. 信任认证

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

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

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

如果通过指定trustpg_hba.conf行让你信任每一个被允许连接到服务器的机器上的用户,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

GSSAPI使用Kerberos时,它在格式servicename/hostname@realm中使用标准 principal。对于 principal 部分的信息以及如何建立所需的密钥,请见Section 19.3.5

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

下列被支持的配置选项用于GSSAPI

include_realm

如果被设置为 1,来自于被认证用户 principal 的领域名被包含在通过用户名映射(Section 19.2)传递的系统用户名中。这对处理来自多个领域的用户非常有用。

map

允许在系统和数据库用户名之间的映射。详见Section 19.2。对于一个 Kerberos principal username/hostbased@EXAMPLE.COM, 如果include_realm被禁用,用于该映射的用户名为username/hostbased,并且如果include_realm被启用,用于该映射的用户名是username/hostbased@EXAMPLE.COM

krb_realm

设置领域为对用户 principal 名进行匹配的范围。如果这个参数被设置,只有那个领域的用户将被接受。如果它没有被设置,任何领域的用户都能连接,服从任何已完成的用户名映射。

19.3.4. SSPI 认证

SSPI是一种用于带单点登录的安全认证的Windows技术。 PostgreSQLnegotiate模式中将使用 SSPI,它在可能的情况下使用Kerberos并在其他情况下自动降回到NTLM。只有在服务器和客户端都运行着Windows时,SSPI才能工作。或者在非 Windows 平台上GSSAPI可用时,SSPI也能工作。

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

下列被支持的配置选项用于SSPI

include_realm

如果被设置为 1,来自于被认证用户 principal 的领域名被包含在通过用户名映射(Section 19.2)传递的系统用户名中。这对处理来自多个领域的用户非常有用。

map

允许在系统和数据库用户名之间的映射。详见Section 19.2

krb_realm

设置领域为对用户 principal 名进行匹配的范围。如果这个参数被设置,只有那个领域的用户将被接受。如果它没有被设置,任何领域的用户都能连接,服从任何已完成的用户名映射。

19.3.5. Kerberos 认证

Note: 本地 Kerberos 认证已被废弃并且应该只被用于向后兼容。新的和升级安装鼓励使用工业标准GSSAPI认证方法(见Section 19.3.3)。

Kerberos是一种适用于在公共网络上进行分布计算的工业标准的安全认证系统。 对Kerberos系统的描述超出了本文档的范围;总地说来它是相当复杂(同样也相当强大)的系统。Kerberos FAQMIT Kerberos 页面是个开始学习的好地方。现在存在好几种Kerberos发布的源代码。Kerberos只提供安全认证,但并不加密在网络上传输的查询或数据,SSL可以用于加密目的。

PostgreSQL支持 Kerberos 版本 5。在编译PostgreSQL时必须打开 Kerberos 支持,详见Chapter 15

PostgreSQL操作起来像一个普通的 Kerberos 服务。服务的 principal 的名字是servicename/hostname@realm

servicename可以在服务器端用krb_srvname配置参数来设置,在客户端可以用连接参数设置(见Section 31.1.2)。在编译时可以使用./configure --with-krb-srvnam=whatever将安装时默认的postgres改掉。在大多数环境下,这个参数从来不需要被改动。但是,当在同一台主机上支持多个PostgreSQL安装时,这就是必须的。有些 Kerberos 实现还可能要求一个不同的服务名, 例如 Microsoft Active Directory 就要求服务名必须是大写的(POSTGRES)。

hostname是服务器机器的的全限定主机名。服务的 principal 的领域就是服务器机器的首选领域。

客户端 principal 必须有它们自己的PostgreSQL用户名作为第一个部件, 例如pgusername@realm。或者,你可以使用一个用户名映射从 principal 名字的第一个组件映射到数据库用户名。 默认情况下,PostgreSQL部检查客户端的领域。如果你启用了跨领域认证并且需要验证领域,请使用krb_realm参数,或者启用include_realm并且使用用户名映射检查领域。

确认你的服务器的 keytab 文件是可以被PostgreSQL服务器帐户读取的(最好是只读的) (又见Section 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.org
kadmin% ktadd -k krb5.keytab postgres/server.my.domain.org

当连接到数据库时,确保你有一个匹配被请求数据库用户名的 principal 的票据。例如,对于数据库用户名fred,principal fred@EXAMPLE.COM将能够连接。要也允许 principal fred/users.example.com@EXAMPLE.COM,可使用一个用户名映射,如Section 19.2中所述。

如果你在你的Apache网页服务器上使用了mod_auth_kerbmod_perl模块, 你可以用一个mod_perl脚本使用AuthType KerberosV5SaveCredentials。这样可以得到一个通过网页的安全数据库访问,不需要额外的口令。

下列被支持的配置选项用于Kerberos

map

允许在系统和数据库用户名之间的映射。详见Section 19.2

include_realm

如果被设置为 1,来自于被认证用户 principal 的领域名被包含在通过用户名映射(Section 19.2)传递的系统用户名中。这对处理来自多个领域的用户非常有用。

krb_realm

设置匹配用户主要名称的范围。如果这个参数 设置了,该领域唯一的用户将被接受。如果没有 设置,任何领域的用户可以连接,服从任何已设置的用户名映射。

krb_server_hostname

设置服务 principal 的主机名部分。它和krb_srvname组合在一起被用来产生完整的服务 principal,那就是krb_srvname/krb_server_hostname@REALM。如果没有设置,默认为服务器主机名。

19.3.6. Ident 认证

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

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

下列被支持的配置选项用于ident

map

允许系统和数据库用户名之间的映射。详见Section 19.2

"Identification Protocol(标识协议)"在 RFC 1413 中描述。实际上每个类 Unix 操作系统都带着一个默认监听 TCP 113 端口的 ident 服务器。ident 服务器的基本功能是回答类似这样的问题:"哪个用户从你的端口X发起了连接并且连到了我的端口Y?" 。因为当一个物理连接被建立后,PostgreSQL既知道X也知道Y, 所以它可以询问尝试连接的客户端主机上的 ident 服务器并且在理论上可以判断任意给定连接的操作系统用户。

这个过程的缺点是它依赖于客户端的完整性:如果客户端机器不可信或者被攻破,攻击者可能在 113 端口上运行任何程序并且返回他选择的任何用户。因此这种认证方法只适用于封闭的网络, 这样的网络中的每台客户端机器都处于严密的控制下并且数据库和操作系统管理员操作时可以方便地联系。换句话说,你必须信任运行 ident 服务器的机器。注意这样的警告:

 

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

 
--RFC 1413 

有些 ident 服务器有一个非标准的选项,它导致返回的用户名是被加密的,使用的是只有原机器管理员知道的一个密钥。当与PostgreSQL配合使用 ident 服务器时,一定不要使用这个选项,因为PostgreSQL没有任何方法对返回的字符串进行解密以获取实际的用户名。

19.3.7. Peer 认证

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

下列被支持的配置选项用于peer

map

允许在系统和数据库用户名之间的映射。详见Section 19.2

Peer 认证只在提供getpeereid()函数、SO_PEERCRED套接字参数或相似机制的操作系统上可用。这些 OS 当前包括Linux、大部分的BSD包括Mac OS X以及Solaris

19.3.8. LDAP 认证

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

LDAP 认证可以在两种模式下操作。在第一种模式中(我们将称之为简单绑定模式),服务器将绑定到构造成prefix username suffix的可区分名称。通常,prefix参数被用于指定 cn=或者一个活动录环境中的DOMAIN\suffix被用来指定非活动目录环境中的DN的剩余部分。

在第二种模式中(我们将称之为搜索与绑定模式),服务器首先用一个固定的用户名和密码(用ldapbinddnldapbindpasswd指定)绑定到 LDAP 目录 ,并为试图登入该数据库的用户执行一次搜索。如果没有配置用户名和密码, 将尝试一次匿名绑定到目录。搜索将在位于ldapbasedn的子树上被执行,并将尝试做一次ldapsearchattribute中指定属性的精确匹配。一旦在这次搜索中找到用户,服务器断开并且作为这个用户重新绑定到目录,使用由客户端指定的口令来验证登录是正确的。这种模式与在其他软件中的 LDAP 认证所使用的相同,例如 Apache mod_authnz_ldap 和 pam_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 连接)不被支持。

LDAP URL 当前只支持 OpenLDAP,而不支持 Windows。

将简单绑定的选项中混合用于搜索与绑定的选项是一种错误。

这里是一个简单绑定 LDAP 配置的例子:

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

当请求一个作为数据库用户someuser到数据库服务器的连接时,PostgreSQL 将尝试使用cn=someuser, dc=example, dc=net和客户端提供的口令来绑定到 LDAP 服务器。如果那个连接成功,将被授予数据库访问。

这里是一个搜索与绑定配置的例子:

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

当请求一个作为数据库用户someuser到数据库服务器的连接时,PostgreSQL 将尝试匿名绑定(因为没有指定ldapbinddn)到 LDAP 服务器,在指定的基础 DN 下执行一次对于(uid=someuser)的搜索。如果找到一个项,则它将尝试使用找到的信息和客户端提供的口令进行绑定。如果第二个连接成功,将被授予数据库访问。

这里是被写成一个 URL 的相同搜索与绑定配置:

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

一些支持根据 LDAP 认证的其他软件使用相同的 URL 格式,因此很容易共享该配置。

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

19.3.9. RADIUS 认证

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

当使用 RADIUS 认证时,一个访问请求消息将被发送到配置好的 RADIUS 服务器。这一请求将是Authenticate Only类型,并且包含参数user namepassword(加密的)和NAS Identifier。该请求将使用一个与服务器共享的密钥加密。RADIUS 服务器将对这个服务器响应Access Accept或者Access Reject。不支持RADIUS accounting。

下列被支持的配置选项用于 RADIUS:

radiusserver

连接到 RADIUS 服务器的名称或IP地址。此参数是必需的。

radiussecret

和 RADIUS 服务器秘密交谈时会用到共享密钥。这在 PostgreSQL 和 RADIUS 服务器之间必须有完全相同的值。我们推荐用一个至少 16 个字符的字符串。这个参数是必需的。

Note: 如果PostgreSQL编译为支持OpenSSL,所用的加密向量将只是强密码。在其他情况下,到 RADIUS 服务器的传输应该被视为应该被视为被混淆的、不安全的。如有必要,应采用外部安全措施。

radiusport

用于连接到 RADIUS 服务器的端口号。如果没有指定端口,则使用默认端口1812

radiusidentifier

在 RADIUS 请求中字符串被用作NAS Identifier。 这个参数可以被用作第二个参数标识例如该用户试图以哪个数据库用户进行认证,它可以被用于 RADIUS 服务器上的策略匹配。如果没有指定标识符,默认使用postgresql

19.3.10. 证书认证

这种认证方法使用 SSL 客户端证书执行认证。因此,它只适用于 SSL 连接。当使用这种认证方法时,服务器将要求客户端提供一个有效的证书。不会有密码提示将被发送到客户端。证书的cn(通用名)属性将与被请求的数据库用户名进行比较,并且如果匹配将允许登录。用户名映射可以被用来允许cn与数据库用户名不同。

下列被支持的配置选项用于 SSL 证书认证:

map

允许在系统和数据库用户名之间的映射。详见Section 19.2

19.3.11. PAM 认证

这种认证方法操作起来类似password, 只不过它使用 PAM (插入式验证模块)作为认证机制。默认的 PAM 服务名是postgresql。PAM 只被用于验证用户名/口令对。因此,在使用 PAM 进行认证之前,用户必须已经存在于数据库中。有关 PAM 的更多信息,请阅读 Linux-PAM 页面.

下列被支持的配置选项用于 PAM:

pamservice

PAM服务名称。

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