19.3. 认证方法

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

19.3.1. 认证方法

如果声明了trust认证模式, PostgreSQL 就假设任何可以连接到服务器的人都可以以任何他声明的数据库用户名 (即便是超级用户)连接。当然,在databaseuser字段里面的限制仍然适用。 这个方法应该用于那些在连接到服务器已经有足够操作系统层次保护的环境里。

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

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

trust认证模式只适合TCP/IP连接, 只有在你信任那些pg_hba.conf行上所有机器中的所有用户的时候才是合适的。 很少有理由使用trust作为任何除来自localhost(127.0.0.1) 以外的TCP/IP连接的认证方式。

19.3.2. 口令认证

以口令为基础的认证方法包括md5password 。 这些方法操作上非常类似,只不过口令通过连接传送的方法不同:MD5散列、crypt加密、明文。 一个限制是crypt不能使用存储在pg_authid中已加密的口令。

如果你担心口令"sniffing"被窃听,那么md5比较合适,简单的password应始终尽量避免。然而,md5不能和db_user_namespace特性一起使用。如果连接受SSL加密保护,那么password使用安全(尽管SSL证书认证可能是一个更好的选择,如果一个是取决于使用SSL)。

PostgreSQL 数据库口令与任何操作系统用户口令无关。各个数据库用户的口令是存储在pg_authid系统表里面。口令可以用SQL语言命令CREATE USERALTER USER等管理(比如CREATE USER foo WITH PASSWORD 'secret'; 。缺省时,如果没有明确设置口令,那么存储的口令是空并且该用户的口令认证总会失败。

19.3.3. GSSAPI认证

GSSAPI是在RFC 2743中定义的安全认证的一个行业标准协议。 PostgreSQL按照RFC 1964支持GSSAPIKerberos认证。 GSSAPI为支持系统提供自动验证(单点登录)。认证本身是安全的,但通过数据库连接发送的数据将不加密发送,除非使用SSL

GSSAPI使用Kerberos, 在形式servicename/hostname@realm 中使用标准格式。对于信息的主要部分,如何建立所需的密钥,参阅Section 19.3.5

当建立PostgreSQL时,GSSAPI支持必须启用,参阅Chapter 15获取详细信息。

GSSAPI下列配置选项:

include_realm

如果设置为1,认证用户的名字范围 主要包括通过用户名映射(Section 19.2)的系统用户名。这对处理来自多个领域的用户非常有用。

map

允许在系统和数据库用户名之间映射。参阅Section 19.2 获得详情。 一个Kerberos原则username/hostbased@EXAMPLE.COM, 如果include_realmusername/hostbased@EXAMPLE.COM被禁用,include_realm被启用,用于映射的用户名是username/hostbased

krb_realm

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

19.3.4. SSPI认证

SSPI是单点登录的安全认证Windows技术。 PostgreSQLnegotiate模式中使用SSPI, 在可能的情况,并自动回落到任何情况下的NTLM时。这将使用Kerberos。 当服务器和客户机正在运行Windows时,仅运行SSPI认证。

当正在使用Kerberos认证时,SSPIGSSAPI 的工作方式相同;参阅Section 19.3.3获得详情。

SSPI支持下列配置选项:

include_realm

如果设置为1,认证用户的名字范围 主要包括通过用户名映射(Section 19.2)的系统用户名。这对处理来自多个领域的用户非常有用。

map

允许系统和数据库的用户名之间映射。参阅Section 19.2获得详情。

krb_realm

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

19.3.5. Kerberos认证

Note: 本地Kerberos认证已过时,只是为了向后兼容。新的和升级安装 鼓励使用行业标准GSSAPI认证方法(参阅Section 19.3.3)。

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

PostgreSQL支持Kerberos 5,Kerberos支持必须在PostgreSQL编译的时候打开。参阅Chapter 15获取更多信息。

PostgreSQL运行时像一个普通的Kerberos服务。 服务主的名字是servicename/hostname@realm

servicename 可以用 krb_srvname 配置参数在服务器端设置, 或者在客户端使用krbsrvname连接参数设置(又见Section 31.1)。编译的时候, 可以把安装时的缺省postgres 修改掉, 方法是使用./configure --with-krb-srvnam=whatever。 在大多数情况下,我们不需要修改这个参数。 但是,如果需要在同一台主机上同时安装多套PostgreSQL , 那么这个就是必须的了。有些Kerberos实现还可能要求其它的服务名, 比如Microsoft Active Directory就要求服务名必须是大写的(POSTGRES)。

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

客户主自己必须用它们自己的PostgreSQL用户名作为第一个部件, 比如pgusername/otherstuff@realm 。另外,你可以使用一个用户名 映射对主体名的第一个组件到数据库用户名。 默认情况下,PostgreSQL没有检查客户的域;如果你有跨域 启用认证和需要验证域,使用krb_realm参数,或启用include_realm 和使用用户名映射到检查域。 因此如果你打开了跨域的认证, 那么在任意域里任何可以和你通讯的主都会被接受。

确认服务器的密钥表文件是可以被 PostgreSQL服务器帐户读取(最好就是只读的) (又见Section 17.1)密钥文件(keytab)的位置是用 配置参数 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

当连接到数据库,确保你有一个主要匹配请求数据库用户名的标签 。例如,对于数据库用户的名称 fred,主要 fred@EXAMPLE.COM将能够连接。也允许 主要fred/users.example.com@EXAMPLE.COM,使用一个用户名地图,正如在Section 19.2 描述的。

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

下面配置选项支持Kerberos:

map

允许系统和数据库的用户名之间映射。参阅Section 19.2获得详情。

include_realm

如果设置为1,认证用户的名字范围 主要包括通过用户名映射(Section 19.2)的系统用户名。这对处理来自多个领域的用户非常有用。

krb_realm

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

krb_server_hostname

设置主服务器主体名称的一部分。 即,连接krb_srvname,用于生成 完整的服务主体,也就是 krb_srvname/krb_server_hostname@REALM。 如果没有设置,默认是服务器主机名。

19.3.6. 给予Ident的认证

ident认证方法是通过获取客户端的操作系统用户名,使用它作为允许数据库用户 名称(可选的用户名映射),判断客户端的用户名是非常关键的安全点,根据连接类型的不同,它的实现方法也略有不同,正如下面描述的。

下面配置选项支持ident:

map

允许在系统和数据库用户名之间匹配。参阅Section 19.2获取详情。

19.3.6.1. 透过TCP/IP的认证

"Identification Protocol"(标识协议) 在RFC 1413里面描述。 实际上每个类Unix的操作系统都带着一个缺省时侦听113端口的身份服务器。 身份服务器的基本功能是回答类似这样的问题: "是什么用户从你的端口X初始化出来连接到我的端口Y上来了?" 。 因为在建立起物理连接后,PostgreSQL既知道X也知道Y, 因此它可以询问运行尝试连接的客户端的主机,并且理论上可以用这个方法判断发起连接的操作系统用户。

这样做的缺点是它取决于客户端的完整性: 如果客户端不可信或者被攻击者攻破, 而且它们可以在113端口上运行任何程序并且返回他们选择的任何用户的话, 就无法认证了。因此这个认证方法只适用于封闭的网络, 这样的网络里的每台客户机都处于严密的控制下并且数据库和操作系统管理员可以比较方便地联系上。 换句话说,你必须信任运行身份(ident)服务的机器。下面是警告:

 

身份标识协议并不适用于认证或者访问控制协议。

 
--RFC 1413 

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

19.3.6.2. 透过本地套接字的身份认证

在支持用于Unix域套接字的SO_PEERCRED请求的系统上 (当前Linux, FreeBSD, NetBSD, OpenBSD, BSD/OS,和Solaris), 身份认证也可以适用于本地连接。 PostgreSQLSO_PEERCRED以找出连接客户端进程的操作系统的名称。 这个时候,使用身份认证不会增加安全风险; 实际上这也是在这种系统上使用本地连接时的首选方法。

在没有SO_PEERCRED请求的系统上, 身份认证只能通过TCP/IP连接获取。 如果需要绕开这个限制, 我们可以声明localhost 地址 127.0.0.1 , 然后让连接指向这个地址。 这个方法适用于你信任本机身份认证服务器的场合。

19.3.7. LDAP认证

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

LDAP身份验证可以在两种模式下运行。在第一种模式中, 服务器将绑定构造的prefix username suffix可分辨名称。 通常情况下,prefix参数用于指定主目录环境下的 cn=, 或者DOMAIN\suffix用来指定非主目录环境中的DN留下的一部分。

在第二种模式中,服务器首先用一个固定的用户名和密码绑定到LDAP目录 ,指定ldapbinduserldapbinddn,并执行一个用户试图登录到数据库的搜索。 如果没有用户名和密码配置, 将尝试匿名绑定到目录。 在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

当做搜索+绑定认证时,归因为在搜索中匹配用户名。

Note: 由于LDAP通常使用逗号和空格分隔不同 DN的部分,当配置LDAP选项,它常常需要使用双引号参数 值,例如:

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

19.3.8. RADIUS认证

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

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

RADIUS支持下列配置选项:

radiusserver

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

radiussecret

当谈到RADIUS服务器,使用共享的秘密。在PostgreSQL和RADIUS服务器必须有相同的值。建议,这是一个至少16个字符的字符串 。此参数是必需的。

Note: 如果PostgreSQL建立支持OpenSSL,使用加密载体将增强加密。 在其他情况下,传输到RADIUS服务器应该被视为混淆,没有保障, 如有必要,应采用外部安全措施。

radiusport

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

radiusidentifier

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

19.3.9. 证书认证

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

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

map

允许在系统和数据库用户名间映射。参阅Section 19.2获取详情。

19.3.10. PAM认证

这个认证方法操作起来类似password , 只不过它使用PAM作为认证机制。 缺省的PAM服务名是postgresql 。 你可以在pg_hba.conf文件的pam关键字后面提供自己的可选服务名。 PAM只用于验证用户名/口令对。 因此,在使用PAM进行认证之前,用户必须已经存在于数据库里。 有关PAM的更多信息,请阅读 Linux-PAM Page页面和 Solaris PAM Page页面。

PAM支持下列配置选项:

pamservice

PAM服务名称。

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