20.3. 身份验证方法

以下小节将更详细地描述身份验证方法。

20 .3.1. 信任认证

当指定trust身份验证时,PostgreSQL 假定可以连接到服务器的任何人都可以使用他们指定的任何数据库用户名(甚至超级用户名)访问数据库。当然,在databaseuser列中所做的限制仍然适用。仅在与服务器的连接上具有足够的 os 级保护时,才应使用此方法。

trust身份验证适用于单用户工作站上的本地连接,并且非常方便。通常,在多用户计算机上,它本身*不**适用。但是,如果使用文件系统权限限制对服务器的 Unix 域套接字文件的访问,则即使在多用户计算机上也可以使用trust。为此,请按照Section 19.3中的说明设置unix_socket_permissions(可能还有unix_socket_group)配置参数。或者,您可以设置unix_socket_directories配置参数以将套接字文件放置在适当限制的目录中。

设置文件系统权限仅对 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

20 .3.2. 密码认证

有几种基于密码的身份验证方法。这些方法的操作类似,但是在用户密码存储在服务器上的方式以及如何通过连接发送 Client 端提供的密码方面有所不同。

  • scram-sha-256

    • RFC 7677中所述,方法scram-sha-256执行 SCRAM-SHA-256 身份验证。它是一种质询-响应方案,可以防止对不信任的连接进行密码嗅探,并支持以加密哈希形式将密码存储在服务器上,这被认为是安全的。

这是当前提供的方法中最安全的方法,但是较旧的 Client 端库不支持此方法。

  • md5

    • 方法md5使用自定义的不太安全的质询-响应机制。它可以防止密码嗅探,并避免将密码以纯文本格式存储在服务器上,但是如果攻击者设法从服务器上窃取密码哈希,则不会提供任何保护。同样,如今,MD5 哈希算法不再被认为可以抵御确定的攻击。

md5方法不能与db_user_namespace功能一起使用。

为了简化从md5方法到较新的 SCRAM 方法的转换,如果在pg_hba.conf中将md5指定为方法,但是服务器上的用户密码已为 SCRAM 加密(请参见下文),则将自动选择基于 SCRAM 的身份验证。

  • password

    • 方法password以明文形式发送密码,因此容易受到密码“嗅探”攻击。如果可能,应始终避免使用它。如果连接受 SSL 加密保护,则可以安全地使用password。 (尽管如果使用 SSL 证书,则使用 SSL 证书身份验证可能是更好的选择)。

PostgreSQL 数据库密码与 os 用户密码分开。每个数据库用户的密码存储在pg_authid系统目录中。可以使用 SQL 命令CREATE USERALTER ROLE,例如 CREATE USER foo WITH PASSWORD 'secret' 或 psql 命令\password来 Management 密码。如果未为用户设置密码,则存储的密码为 null,并且该用户的密码身份验证将始终失败。

不同的基于密码的身份验证方法的可用性取决于服务器上用户密码的加密方式(或更准确地说,是散列的)。设置密码时,此设置由配置参数password_encryption控制。如果使用scram-sha-256设置对密码进行了加密,则可以将其用于scram-sha-256password身份验证方法(但在后一种情况下,密码将以纯文本格式传输)。如上所述,在这种情况下,身份验证方法规范md5将自动切换为使用scram-sha-256方法,因此它也将起作用。如果使用md5设置对密码进行了加密,则该密码只能用于md5password身份验证方法规范(同样,密码在后一种情况下以纯文本格式传输)。 (以前的 PostgreSQL 版本支持将密码以纯文本格式存储在服务器上.这不再可能.)要检查当前存储的密码哈希,请参见系统目录pg_authid

在确保所有正在使用的 Client 端库足够新以支持 SCRAM 之后,要将现有安装从md5升级到scram-sha-256,请在postgresql.conf中设置password_encryption = 'scram-sha-256',让所有用户设置新密码,并将pg_hba.conf的身份验证方法规范更改为scram-sha-256

20 .3.3. GSSAPI 身份验证

GSSAPI 是 RFC 2743 中定义的用于安全身份验证的行业标准协议。PostgreSQL 根据 RFC 1964 支持带有 Kerberos 身份验证的 GSSAPI。GSSAPI 为支持它的系统提供自动身份验证(单点登录)。身份验证本身是安全的,但是除非使用 SSL,否则通过数据库连接发送的数据将以未加密的方式发送。

构建 PostgreSQL 时必须启用 GSSAPI 支持。有关更多信息,请参见Chapter 16

当 GSSAPI 使用 Kerberos 时,它使用格式servicename/hostname@realm的标准主体。 PostgreSQL 服务器将接受服务器使用的密钥表中包含的任何主体,但是在使用krbsrvname连接参数从 Client 端进行连接时,需要注意指定正确的主体详细信息。 (另请参见Section 33.1.2。)可以在构建时使用./configure --with-krb-srvnam= * whatever *从默认的postgres更改安装默认值。在大多数环境中,无需更改此参数。某些 Kerberos 实现可能需要不同的服务名称,例如 Microsoft Active Directory,它要求服务名称为大写(POSTGRES)。

  • hostname *是服务器计算机的标准主机名。服务主体的领域是服务器计算机的首选领域。

Client 端主体可以使用pg_ident.confMap 到不同的 PostgreSQL 数据库用户名。例如,pgusername@realm可以仅 Map 到pgusername。另外,您可以使用完整的username@realm主体作为 PostgreSQL 中的角色名称,而无需任何 Map。

PostgreSQL 还支持从主体剥离领域的参数。支持此方法以实现向后兼容,因此强烈建议不要使用此方法,因为这样就不可能区分具有相同用户名但来自不同领域的不同用户。要启用此功能,请将include_realm设置为 0.对于简单的单领域安装,将其与设置krb_realm参数(检查主体的领域是否与krb_realm参数中的内容完全匹配)结合起来仍然是安全的。但与在pg_ident.conf中指定显式 Map 相比,这是一种功能较弱的方法。

确保 PostgreSQL 服务器帐户可读取您的服务器密钥表文件(最好仅可读取,不可写入)。 (另请参见Section 18.1。)密钥文件的位置由krb_server_keyfile配置参数指定。默认值为/usr/local/pgsql/etc/krb5.keytab(或在构建时指定为sysconfdir的任何目录)。出于安全原因,建议仅对 PostgreSQL 服务器使用单独的密钥表,而不要对系统密钥表文件开放权限。

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,主体[email protected]将能够连接。要也允许主体fred/[email protected],请使用用户名 Map,如Section 20.2中所述。

GSSAPI 支持以下配置选项:

  • include_realm

    • 如果设置为 0,则在通过用户名 Map(Section 20.2)之前,将剥离已认证用户主体的领域名称。不建议这样做,并且主要用于向后兼容,因为除非在多领域环境中使用krb_realm,否则它也不安全。建议将include_realm设置为默认值(1),并在pg_ident.conf中提供显式 Map,以将主体名称转换为 PostgreSQL 用户名。
  • map

    • 允许在系统用户名和数据库用户名之间进行 Map。有关详情,请参见Section 20.2。对于 GSSAPI/Kerberos 主体,例如[email protected](或更不常见的是username/[email protected]),用于 Map 的用户名是[email protected](或分别为username/[email protected]),除非include_realm已设置为 0,在这种情况下为username(或username/hostbased)。Map 时被视为系统用户名。
  • krb_realm

    • 设置领域以匹配用户主体名称。如果设置了此参数,则仅接受该领域的用户。如果未设置,则无论完成任何用户名 Map,任何领域的用户都可以连接。

20 .3.4. SSPI 验证

SSPI 是一种 Windows 技术,用于通过单点登录进行安全身份验证。 PostgreSQL 将在negotiate模式下使用 SSPI,并在可能的情况下使用 Kerberos,在其他情况下会自动退回到 NTLM。仅当服务器和 Client 端都运行 Windows 时,或者在非 Windows 平台上,当 GSSAPI 可用时,SSPI 身份验证才起作用。

使用 Kerberos 身份验证时,SSPI 的工作方式与 GSSAPI 相同。有关详情,请参见Section 20.3.3

SSPI 支持以下配置选项:

  • include_realm

    • 如果设置为 0,则在通过用户名 Map(Section 20.2)之前,将剥离已认证用户主体的领域名称。不建议这样做,并且主要用于向后兼容,因为除非在多领域环境中使用krb_realm,否则它也不安全。建议将include_realm设置为默认值(1),并在pg_ident.conf中提供显式 Map,以将主体名称转换为 PostgreSQL 用户名。
  • compat_realm

    • 如果设置为 1,则include_realm选项使用域的 SAM 兼容名称(也称为 NetBIOS 名称)。这是默认值。如果设置为 0,则使用 Kerberos 用户主体名称中的真实领域名称。

除非您的服务器在域帐户下运行(包括域成员系统上的虚拟服务帐户),并且所有通过 SSPI 进行身份验证的 Client 端也都在使用域帐户,否则身份验证将失败,请不要禁用此选项。

  • upn_username

    • 如果与compat_realm一起启用此选项,则使用 Kerberos UPN 中的用户名进行身份验证。如果禁用(默认),则使用 SAM 兼容用户名。默认情况下,这两个名称对于新用户帐户是相同的。

请注意,如果未指定显式用户名,则 libpq 使用 SAM 兼容名称。如果使用 libpq 或基于 libpq 的驱动程序,则应禁用此选项或在连接字符串中显式指定用户名。

  • map

    • 允许在系统用户名和数据库用户名之间进行 Map。有关详情,请参见Section 20.2。对于 SSPI/Kerberos 主体,例如[email protected](或更不常见的是username/[email protected]),用于 Map 的用户名是[email protected](或分别为username/[email protected]),除非include_realm已设置为 0,在这种情况下为username(或username/hostbased)。Map 时被视为系统用户名。
  • krb_realm

    • 设置领域以匹配用户主体名称。如果设置了此参数,则仅接受该领域的用户。如果未设置,则无论完成任何用户名 Map,任何领域的用户都可以连接。

20 .3.5. 身份认证

身份验证方法的工作方式是从 ident 服务器获取 Client 端的 os 用户名,并将其用作允许的数据库用户名(具有可选的用户名 Map)。仅在 TCP/IP 连接上支持此功能。

Note

当为本地(非 TCP/IP)连接指定了 ident 时,将使用对等身份验证(请参阅Section 20.3.6)。

ident 支持以下配置选项:

  • map

    • 允许在系统用户名和数据库用户名之间进行 Map。有关详情,请参见Section 20.2

RFC 1413 中描述了“标识协议”。实际上,每个类 Unixos 都附带一个标识服务器,默认情况下,该服务器侦听 TCP 端口 113. ident 服务器的基本功能是回答诸如“什么用户发起了从端口* X 断开并连接到我的端口 Y * 的连接”之类的问题。由于 PostgreSQL 在构建物理连接时都知道 X Y *,因此它可以查询连接 Client 端主机上的 ident 服务器,并且理论上可以确定任何给定连接的 os 用户。

此过程的缺点在于,它取决于 Client 端的完整性:如果 Client 端计算机不受信任或受到威胁,攻击者可能会在端口 113 上几乎运行任何程序并返回他们选择的任何用户名。因此,此身份验证方法仅适用于封闭网络,在封闭网络中,每台 Client 端计算机都受到严格控制,并且数据库和系统 Management 员紧密联系。换句话说,您必须信任运行身份服务器的计算机。注意警告:

标识协议不打算用作授权或访问控制协议。
--RFC 1413

某些 ident 服务器具有非标准选项,该选项使用仅原始计算机 Management 员知道的密钥来使返回的用户名被加密。在 ident 服务器和 PostgreSQL 一起使用时,不得使用该选项,因为 PostgreSQL 无法解密返回的字符串来确定实际的用户名。

20 .3.6. 对等身份验证

对等身份验证方法的工作原理是从内核获取 Client 端的 os 用户名,并将其用作允许的数据库用户名(具有可选的用户名 Map)。仅本地连接支持此方法。

对等方支持以下配置选项:

  • map

    • 允许在系统用户名和数据库用户名之间进行 Map。有关详情,请参见Section 20.2

对等身份验证仅在提供getpeereid()功能,SO_PEERCRED套接字参数或类似机制的 os 上可用。当前包括 Linux,大多数版本的 BSD(包括 macOS)和 Solaris。

20 .3.7. LDAP 验证

除了使用 LDAP 作为密码验证方法之外,此身份验证方法的操作与password相似。 LDAP 仅用于验证用户名/密码对。因此,用户必须已经存在于数据库中,然后才能使用 LDAP 进行身份验证。

LDAP 身份验证可以两种方式运行。在第一种模式下,我们将其称为简单绑定模式,服务器将绑定到以* prefix * * username * * suffix 构造的专有名称。通常, prefix 参数用于在 Active Directory 环境中指定cn= DOMAIN * \。 * suffix *用于指定非 Active Directory 环境中 DN 的其余部分。

在第二种模式(我们将其称为搜索绑定模式)中,服务器首先使用固定的用户名和密码(由* ldapbinddn ldapbindpasswd 指定)绑定到 LDAP 目录,然后对尝试登录的用户执行搜索进入数据库。如果未配置用户名和密码,则将尝试匿名绑定到目录。搜索将在 ldapbasedn 的子树上进行,并将尝试与 ldapsearchattribute *中指定的属性完全匹配。在此搜索中找到用户后,服务器将使用 Client 端指定的密码以该用户身份断开连接并重新绑定到目录,以验证登录名是否正确。此模式与其他软件(例如 Apache mod_authnz_ldappam_ldap)中的 LDAP 认证方案所使用的模式相同。该方法在用户对象在目录中的位置上提供了极大的灵 Active,但是会导致与 LDAP 服务器构建两个单独的连接。

在两种模式下都使用以下配置选项:

  • ldapserver

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

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

    • 设置为 1 可使 PostgreSQL 和 LDAP 服务器之间的连接使用 TLS 加密。请注意,这只会加密到 LDAP 服务器的流量-除非使用 SSL,否则到 Client 端的连接仍将是未加密的。

以下选项仅在简单绑定模式下使用:

  • 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 的其他一些组件,例如过滤器和 extensions。

对于非匿名绑定,必须将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 将尝试使用 DN cn=someuser, dc=example, dc=net和 Client 端提供的密码绑定到 LDAP 服务器。如果该连接成功,则将授予数据库访问权限。

这是搜索绑定配置的示例:

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

当请求以数据库用户someuser的身份与数据库服务器构建连接时,PostgreSQL 将尝试匿名绑定(由于未指定ldapbinddn)到 LDAP 服务器,并在指定的基本 DN 下执行(uid=someuser)的搜索。如果找到条目,它将尝试使用找到的信息和 Client 端提供的密码进行绑定。如果第二个连接成功,则将授予数据库访问权限。

这是写为 URL 的相同搜索绑定配置:

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

其他一些支持 LDAP 身份验证的软件使用相同的 URL 格式,因此共享配置会更加容易。

Tip

由于 LDAP 通常使用逗号和空格来分隔 DN 的不同部分,因此在配置 LDAP 选项时通常需要使用双引号参数值,如示例所示。

20 .3.8. RADIUS 认证

除了使用 RADIUS 作为密码验证方法之外,此身份验证方法的操作与password相似。 RADIUS 仅用于验证用户名/密码对。因此,用户必须已经存在于数据库中,然后才能使用 RADIUS 进行身份验证。

使用 RADIUS 身份验证时,访问请求消息将发送到配置的 RADIUS 服务器。该请求的类型将为Authenticate Only,并包含user namepassword(已加密)和NAS Identifier的参数。该请求将使用与服务器共享的机密进行加密。 RADIUS 服务器将使用Access AcceptAccess Reject响应此请求。不支持 RADIUS 记帐。

可以指定多个 RADIUS 服务器,在这种情况下将依次尝试。如果从服务器收到否定响应,则身份验证将失败。如果没有收到响应,将尝试列表中的下一个服务器。要指定多个服务器,请用逗号分隔服务器名称,并在列表中用双引号引起来。如果指定了多个服务器,则其他 RADIUS 选项也可以作为逗号分隔的列表给出,以为每个服务器提供单独的值。也可以将它们指定为单个值,在这种情况下,该值将应用于所有服务器。

RADIUS 支持以下配置选项:

  • radiusservers

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

    • 安全地与 RADIUS 服务器通信时使用的共享机密。在 PostgreSQL 和 RADIUS 服务器上,该值必须完全相同。建议使用至少 16 个字符的字符串。此参数是必需的。

Note

如果 PostgreSQL 是在支持 OpenSSL 的情况下构建的,则所使用的加密矢量仅具有加密强度。在其他情况下,仅应考虑到到 RADIUS 服务器的传输是混乱的,而不是安全的,并且在必要时应采用外部安全措施。

  • radiusports

    • RADIUS 服务器上要连接的端口号。如果未指定端口,则将使用默认的 RADIUS 端口(1812)。
  • radiusidentifiers

    • 在 RADIUS 请求中用作NAS Identifier的字符串。例如,此参数可用于标识用户尝试连接到哪个数据库集群,这对于 RADIUS 服务器上的策略匹配很有用。如果未指定标识符,将使用默认的postgresql

如果必须在 RADIUS 参数值中使用逗号或空格,可以通过在值周围加上双引号来完成,但这很麻烦,因为现在需要两层双引号。将空格放入 RADIUS 机密字符串的示例如下:

host ... radius radiusservers="server1,server2" radiussecrets="""secret one"",""secret two"""

20 .3.9. 证书认证

此身份验证方法使用 SSLClient 端证书执行身份验证。因此,它仅适用于 SSL 连接。使用此身份验证方法时,服务器将要求 Client 端提供有效的可信证书。没有密码提示将发送给 Client 端。证书的cn(公用名)属性将与请求的数据库用户名进行比较,如果匹配,则允许登录。用户名 Map 可用于允许cn与数据库用户名不同。

SSL 证书身份验证支持以下配置选项:

  • map

    • 允许在系统用户名和数据库用户名之间进行 Map。有关详情,请参见Section 20.2

在指定证书认证的pg_hba.confLogging,认证选项clientcert假定为1,由于该方法需要 Client 端证书,因此无法将其关闭。 cert方法添加到基本clientcert证书有效性测试的目的是检查cn属性是否与数据库用户名匹配。

20 .3.10. PAM 验证

除了使用 PAM(可插入身份验证模块)作为身份验证机制外,此身份验证方法与password相似。默认的 PAM 服务名称是postgresql。 PAM 仅用于验证用户名/密码对以及可选的已连接远程主机名或 IP 地址。因此,用户必须已经存在于数据库中,然后才能使用 PAM 进行身份验证。有关 PAM 的更多信息,请阅读Linux-PAM Page

PAM 支持以下配置选项:

  • pamservice

    • PAM 服务名称。
  • pam_use_hostname

    • 确定是否通过PAM_RHOST项将远程 IP 地址或主机名提供给 PAM 模块。默认情况下,使用 IP 地址。将此选项设置为 1 可改为使用解析的主机名。主机名解析可能导致登录延迟。 (大多数 PAM 配置不使用此信息,因此,只有专门创建 PAM 配置来使用它时,才需要考虑此设置.)

Note

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

20 .3.11. BSD 验证

除了使用 BSD 身份验证来验证密码外,此身份验证方法与password相似。 BSD 身份验证仅用于验证用户名/密码对。因此,在将 BSD 身份验证用于身份验证之前,数据库中必须已经存在用户角色。 BSD 身份验证框架当前仅在 OpenBSD 上可用。

PostgreSQL 中的 BSD 身份验证使用auth-postgresql登录类型,并在login.conf中定义时使用postgresql登录类进行身份验证。默认情况下,该登录类不存在,而 PostgreSQL 将使用默认的登录类。

Note

要使用 BSD 身份验证,必须首先将 PostgreSQL 用户帐户(即运行服务器的 os 用户)添加到auth组。默认情况下,auth组存在于 OpenBSD 系统上。