ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 19.3\. 认证方法 下面的小节更详细地描述认证方法。 ## 19.3.1\. 信任认证 如果声明了`trust`认证模式,PostgreSQL 就假设任何可以连接到服务器的人都可以以任何他声明的数据库用户名(甚至超级用户名)连接。 当然,在`database`和`user`字段里面的限制仍然适用。 这个方法应该用于那些在连接到服务器已经有足够操作系统层次保护的环境里。 `trust`认证对于单用户工作站的本地连接是非常合适和方便的。 通常它本身并_不_适用于多用户环境的机器。不过,即使在多用户的机器上, 你也可以使用`trust`,只要你利用文件系统权限限制了对服务器的 Unix 域套接字文件的访问。 要做这些限制,你可以设置`unix_socket_permissions`参数(以及可能还有 `unix_socket_group`),就像[Section 18.3](#calibre_link-1242)里描述的那样。 或者你可以设置`unix_socket_directories`,把 Unix 域套接字文件放在一个经过恰当限制的目录里。 设置文件系统权限只能帮助 Unix 套接字连接,它不会限制本地 TCP/IP 连接。因此, 如果你想利用文件系统权限来控制本地安全,那么删除`pg_hba.conf`文件中的 `host ... 127.0.0.1 ...`行,或者把它改为一个非`trust`的认证方法。 `trust`认证模式只适合 TCP/IP 连接,只有在你信任那些`trust` 行上所有机器中的所有用户的时候才是合适的。 很少有理由使用`trust`作为任何除来自localhost (127.0.0.1) 以外的 TCP/IP 连接的认证方式。 ## 19.3.2\. 口令认证 以口令为基础的认证方法包括`md5`,`password`。这些方法操作上非常类似, 只不过口令通过连接传送的方法不同:分别是MD5 散列、明文。 如果你担心口令被"窃听",那么`md5`比较合适。 应该尽可能避免使用`password`。然而,`md5`不能和 [db_user_namespace](#calibre_link-1563)功能一起使用。如果连接通过SSL加密保护, 那么`password`可以安全的使用(尽管如果一个用户依赖于使用SSL, SSL证书认证可能是一个更好的选择。) PostgreSQL数据库口令与任何操作系统用户口令无关。 各个数据库用户的口令是存储在`pg_authid`系统表里面。 口令可以用 SQL 语言命令[CREATE USER](#calibre_link-15)和[ALTER ROLE](#calibre_link-17) 等管理(比如&lt;kbd class="literal"&gt;CREATE USER foo WITH PASSWORD 'secret'&lt;/kbd&gt;。 如果没有明确设置口令,那么存储的口令是空并且该用户的口令认证总会失败。 ## 19.3.3\. GSSAPI 认证 GSSAPI是为了在RFC 2743中定义的安全认证的一个工业标准协议。 PostgreSQL根据RFC 1964支持GSSAPI 和Kerberos认证一起使用。GSSAPI 为支持它的系统提供自动身份验证(单点登录)。身份验证本身是安全的, 但是数据在数据连接时的传送将会是未加密的,除非使用了SSL。 当GSSAPI使用Kerberos时,它使用一个标准, 主要以`_servicename_`/`_hostname_`@`_realm_`的格式。 关于主要部分的信息和如何配置所需的秘钥,请参阅[Section 19.3.5](#calibre_link-504)。 GSSAPI支持在PostgreSQL编译时必须打开;参阅[Chapter 15](#calibre_link-1156)获取更多信息。 GSSAPI支持下列的配置选项: `include_realm` 如果设置为1,通过身份验证的用户主的域名包含在通过用户名映射的系统用户名中([Section 19.2](#calibre_link-1258))。 这对处理来自多个领域的用户是有帮助的。 `map` 允许在系统和数据库用户名之间映射。参阅[Section 19.2](#calibre_link-1258)获取细节。 对于一个Kerberos主要的`username/hostbased@EXAMPLE.COM`, 如果`include_realm`未启用,那么用来映射的用户名是`username/hostbased`, 如果`include_realm`启用了,那么就是`username/hostbased@EXAMPLE.COM`。 `krb_realm` 设置域以匹配用户主名称。如果设置了这个参数,那么只接受那个域中的用户。如果没有设置, 那么任何域中的用户都可以连接,使无论什么用户名映射都完成。 ## 19.3.4\. SSPI 认证 SSPI是单点登录安全身份验证的一个Windows技术。 PostgreSQL将在`negotiate`模式下使用SSPI, 当可能时将使用Kerberos并且在其他情况下会自动回滚至NTLM。 SSPI认证只当服务器和客户端都运行Windows时工作, 否则,在非Windows平台上,GSSAPI是可用的。 当使用Kerberos认证时,SSPI以和GSSAPI 一样的方式工作;参阅[Section 19.3.3](#calibre_link-505)获取详细信息。 SSPI支持下列的配置选项: `include_realm` 如果设置为1,通过身份验证的用户主的域名包含在通过用户名映射的系统用户名中([Section 19.2](#calibre_link-1258))。 这对处理来自多个领域的用户是有帮助的。 `map` 允许在系统和数据库用户名之间映射。参阅[Section 19.2](#calibre_link-1258)获取细节。 `krb_realm` 设置域以匹配用户主名称。如果设置了这个参数,那么只接受那个域中的用户。如果没有设置, 那么任何域中的用户都可以连接,使无论什么用户名映射都完成。 ## 19.3.5\. Kerberos 认证 > **Note:** 本地Kerberos认证已经废弃了而且应该只在为了向后兼容的时候使用。 建议新的和升级安装使用工业标准GSSAPI认证方法(参阅[Section 19.3.3](#calibre_link-505))。 Kerberos是一种适用于在公共网络上进行分布计算的工业标准的安全认证系统。 对Kerberos系统的叙述超出了本文档的范围; 总的说来它是相当复杂(同样也相当强大)的系统。 [Kerberos FAQ](http://www.cmf.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html)或[MIT Kerberos page](http://web.mit.edu/kerberos/www/) 是个开始学习的好地方。现存在好几种Kerberos发布的源代码。Kerberos 只提供安全认证,但并不加密在网络上传输的查询和数据,SSL可以用于这个目的。 PostgreSQL支持 Kerberos 5 ,Kerberos 支持必须在编译的时候打开。 参阅[Chapter 15](#calibre_link-1156)获取更多信息。 PostgreSQL运行时像一个普通的 Kerberos 服务。服务主的名字是 `_servicename_`/`_hostname_`@`_realm_`。 `_servicename_`可以用[krb_srvname](#calibre_link-1564)配置参数在服务器端设置, 或者在客户端使用`krbsrvname`连接参数设置(又见[Section 31.1.2](#calibre_link-498))。 编译的时候,可以把安装时的缺省`postgres`修改掉,方法是使用 `./configure --with-krb-srvnam=``_whatever_`。在大多数情况下, 我们不需要修改这个参数。但是,如果需要在同一台主机上同时安装多套PostgreSQL, 那么这个就是必须的了。有些 Kerberos 实现还可能要求其它的服务名, 比如 Microsoft Active Directory 就要求服务名必须是大写的(`POSTGRES`)。 `_hostname_` 是服务器的全限定主机名。服务主的领域就是主机的首选领域。 客户主自己必须用它们自己的PostgreSQL用户名作为第一个部件, 比如`pgusername@realm`。或者,你可以使用一个用户名映射来从主名的第一个部件到数据库用户名映射。 缺省的,PostgreSQL没有检查客户的域;因此如果你打开了跨域的认证,并且需要验证这个域, 那么使用`krb_realm`参数或者打开`include_realm`并使用用户名映射来检查这个域。 确认服务器的密钥表文件是可以被PostgreSQL服务器帐户读取 (最好就是只读的)。(又见[Section 17.1](#calibre_link-1237)。)密钥文件(keytab)的位置是用配置参数 [krb_server_keyfile](#calibre_link-1565)声明的。缺省是`/usr/local/pgsql/etc/krb5.keytab` (或者任何在编译的时候声明为`sysconfdir`的目录)。 密钥表文件(keytab)是在 Kerberos 软件里生成的,参阅 Kerberos 文档获取细节。 下面的例子是可以用于 MIT 兼容的 Kerberos 5 实现: ``` <samp class="literal">kadmin%</samp> <kbd class="literal">ank -randkey postgres/server.my.domain.org</kbd> <samp class="literal">kadmin%</samp> <kbd class="literal">ktadd -k krb5.keytab postgres/server.my.domain.org</kbd> ``` 在和数据库连接的时候,请确保自己对每个主都拥有一张匹配所请求的数据库用户名的门票。 比如,对于数据库用户`fred`,主`fred@EXAMPLE.COM`将能够连接。 为了也允许主`fred/users.example.com@EXAMPLE.COM`,使用一个用户名映射, 在[Section 19.2](#calibre_link-1258)中描述。 如果你在Apache服务器上使用了 [mod_auth_kerb](http://modauthkerb.sf.net) 和mod_perl模块,你可以用一个mod_perl 脚本进行`AuthType KerberosV5SaveCredentials`。 这样就有了一个通过 web 的安全数据库访问,不需要额外的口令。 Kerberos支持下列的配置选项: `map` 允许系统和数据库用户名之间的映射。参阅[Section 19.2](#calibre_link-1258)获取详细信息。 `include_realm` 如果设置为1,通过身份验证的用户主的域名包含在通过用户名映射的系统用户名中([Section 19.2](#calibre_link-1258))。 这对处理来自多个领域的用户是有帮助的。 `krb_realm` 设置域以匹配用户主名称。如果设置了这个参数,那么只接受那个域中的用户。如果没有设置, 那么任何域中的用户都可以连接,使无论什么用户名映射都完成。 `krb_server_hostname` 设置服务主的主机名部分。与`krb_srvname`组合,用来产生全部的服务主,也就是 `krb_srvname``/``krb_server_hostname``@`域。 如果没有设置,缺省为服务器主机名。 ## 19.3.6\. Ident 认证 ident 认证方法是通过从一个ident服务器获取客户端的操作系统用户名, 并使用它作为允许的数据库用户名(带有一个可选的用户名映射)。 只在TCP/IP连接上支持。 > **Note:** 当ident指定为本地连接(非TCP/IP)时,将使用peer的认证(参阅[Section 19.3.7](#calibre_link-503))。 ident支持下列的配置选项: `map` 允许在系统和数据库用户名之间映射。参阅[Section 19.2](#calibre_link-1258)获取详细信息。 "Identification Protocol"(标识协议)在 RFC 1413 里面描述。 实际上每个类 Unix 的操作系统都带着一个缺省时侦听 113 端口的身份服务器。 身份服务器的基本功能是回答类似这样的问题:"是什么用户从你的端口 `_X_`初始化出来连接到我的端口`_Y_`上来了?"。 因为在建立起物理连接后,PostgreSQL既知道`_X_`也知道`_Y_`, 因此它可以询问运行尝试连接的客户端的主机,并且理论上可以判断发起连接的操作系统用户。 这样做的缺点是它取决于客户端的完整性:如果客户端不可信或者被盗用, 那么攻击者可以在 113 端口上运行任何程序并且返回他们选择的任何用户。 这个认证方法只适用于封闭的网络, 这样的网络里的每台客户机都处于严密的控制下并且数据库和操作系统管理员可以比较方便地联系上。 换句话说,你必须信任运行身份(ident)服务的机器。下面是警告: 身份标识协议并不适用于认证或者访问控制协议。 --RFC 1413 有些身份服务器有一个非标准的选项,导致返回的用户名是加密的, 使用的是只有原机器的管理员知道的一个密钥。在与PostgreSQL配合使用身份认证的时候, 你_一定不能_使用这个选项,因为PostgreSQL 没有任何方法对返回的字符串进行解密以获取实际的用户名。 ## 19.3.7\. Peer 认证 peer认证方法通过从内核获得客户端的操作系统用户名和使用它作为允许的数据库用户名 (使用可选的用户名映射)工作。这个方法只支持本地连接。 peer支持下列的配置选项: `map` 允许在系统和数据库用户名之间映射。参阅[Section 19.2](#calibre_link-1258)获取详细信息。 Peer认证只能在提供`getpeereid()`函数、`SO_PEERCRED` 套接字参数或类似的机制的操作系统上适用,目前包括Linux、 大多数包含Mac OS X的BSD 和Solaris。 ## 19.3.8\. LDAP 认证 这个认证方法操作起来类似`password`,只不过它使用 LDAP 作为密码验证机制。 LDAP 只用于验证用户名/口令对。因此,在使用 LDAP 进行认证之前,用户必须已经存在于数据库里。 LDAP认证可以在两种模式操作。在第一种模式,我们将调用简单的绑定模式, 服务器将绑定到以`_prefix_` `_username_` `_suffix_` 构造的识别名(Distinguished Name)上。通常`_prefix_` 参数用于在活动目录环境中指定`cn=`或`_DOMAIN_``\`。 `_suffix_`用来在非活动目录环境中指定DN的剩余部分。 在第二种模式中,我们将调用搜索+绑定模式,服务器首先绑定到LDAP目录上,带有固定用户名和密码, 用`_ldapbinddn_`和`_ldapbindpasswd_`指定,并且为试图登陆到数据库的用户执行一次搜索。 如果没有配置用户名和密码,将试图对这个目录进行匿名绑定。将对在`_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_`必须是`base`, `one`, `sub`之一,通常是最后一个。只使用一个属性, 一些其他的标准LDAP URL的组成部分比如filters和extensions是不支持的。 对于非匿名的绑定, `ldapbinddn`和`ldapbindpasswd` 必须作为独立的选项声明。 要使用加密的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`绑定到LDAP服务器, 并且密码由客户端提供。如果那个连接成功了,那么就同意数据库访问。 这里是搜索+绑定配置的一个例子: ``` host ... ldap ldapserver=ldap.example.net ldapbasedn="dc=example, dc=net" ldapsearchattribute=uid ``` 当要求一个到数据库服务器的连接作为数据库用户`someuser`时, PostgreSQL将试图匿名(因为没有指定`ldapbinddn`)绑定到LDAP服务器, 为`(uid=someuser)`在指定的基础DN下执行一个搜索。如果发现一条记录, 它将试图使用发现的信息和客户端提供的密码绑定。如果第二个链接成功,那么就同意数据库访问。 这是相同的搜索+绑定配置,写作一个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 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.10\. 证书认证 这个认证方法使用SSL证书来执行认证。因此只适用于SSL连接。当使用这个认证方法时, 服务器将请求客户端提供一个有效的证书。没有密码提示发送给客户端。 证书的`cn` (Common Name) 属性将与请求的数据库用户名比较, 如果它们匹配,登陆将被允许。用户名映射可以用来允许`cn`不同于数据库用户名。 SSL证书认证支持下列的配置选项: `map` 允许在系统和数据库用户名之间映射。参阅[Section 19.2](#calibre_link-1258)获取详细信息。 ## 19.3.11\. PAM 认证 这个认证方法操作起来类似`password`,只不过它使用 PAM (Pluggable Authentication Modules)作为认证机制。缺省的 PAM 服务名是`postgresql`。 PAM 只用于验证用户名/口令对。因此,在使用 PAM 进行认证之前,用户必须已经存在于数据库里。 有关 PAM 的更多信息,请阅读 [Linux-PAM页面](http://www.kernel.org/pub/linux/libs/pam/)。 PAM支持下列的配置选项: `pamservice` PAM服务名。 > **Note:** 如果PAM设置为读取`/etc/shadow`,那么将验证失败,因为PostgreSQL服务器是通过非root用户启动的。 然而,当PAM设置为使用LDAP或其他认证方法时将不是一个问题。