9.1第十九章

From PostgreSQL wiki
Jump to navigationJump to search

第十九章 客户端认证

当一个客户端应用连接数据库服务器的时候,它需要指定将以哪个PostgreSQL数据库的用户名进行连接,就像我们用指定的用户去登陆一台Unix。在SQL环境中,活跃的数库用户名确定了数据库对象的访问权限--请参阅第二十章获取更多的信息。因此,我们只需要限制用户可以连接的数据库。

     注意:正如在第二十章所述,PostgreSQL其实是用角色进行权限管理,在这一章节,我们用从数据库用户的角度来讲“角色的登录权限”。

认证是数据库服务器建立客户端的标识,然后通过某种方法确定是否允许客户端应用(或者说是运行这个客户端应用的用户)能否用请求的用户名进行连接。 PostgreSQL提供许多不同的客户端认证方式。认证某个特定客户端联接所使用的方法可以通过基于(客户端)的主机地址,数据库和用户的方式进行选择。 PostgreSQL数据库用户名在逻辑上是和我们运行这个数据库服务器的操作系统的用户名是相互独立的。如果某个服务的所有用户在其他有这个服务的机器上也有帐号,那么给数据库用户赋与操作系统用户名是有意义的。不过,一个接受远程连接的服务器上可能有许多数据库用户但是在本地操作系统上没有的同名的账户,在这种情况下数据库用户和操作系统用户名之间不必有任何联系。

19.1 pg_hba.conf文件

客户端认证是由一个配置文件控制的,通常文件名为pg_hba.conf并且存放在数据库集群的数据目录中。(HBA 的意思是 host-based authentication:基于主机的认证。当用initdb命令初始化一个数据目录的时候,pg_hba.conf将被缺省安装。不过,我们也可以将认证文件放到其他地方;参阅hba_file配置参数.

pg_hba.conf文件的一般格式是每一行一条记录,空行将被忽略,在#符后的文字都将注释掉。记录不能跨行。一条记录是由若干用空格和/或 tab 分隔的字段组成。如果字段用引号包围。引用了数据库里的关键字例,用户或者地址字段(例如:其他所有的或者复制)将会失去他们特殊的含义,只是和数据库里的用户和主机同名而已。 每一个记录都指定了一个连接类型,一个客户端IP范围(如果和连接类型相关),一个数据库名,一个用户名,以及匹配这些连接参数的认证方法。拥有连接类型,客户端IP地址,请求连接的数据库名和用户名的第一条记录将会被执行认证。这个过程没有“跨越”和“回头”的说法;如果选择了一条记录并且认证失败,那么将不会考虑后面的记录。如果没有记录匹配,访问将会被禁止。

每条记录可以是以下七种格式之一:

      local      database  user  auth-method  [auth-options]
      host       database  user  address  auth-method  [auth-options]
      hostssl    database  user  address  auth-method  [auth-options]
      hostnossl  database  user  address  auth-method  [auth-options]
      host       database  user  IP-address  IP-mask  auth-method  [auth-options]
      hostssl    database  user  IP-address  IP-mask  auth-method  [auth-options]
      hostnossl  database  user  IP-address  IP-mask  auth-method  [auth-options]

各个字段的含义如下:

   local

这个记录匹配通过unix套接字的进行的连接请求。没有这种类型的记录,unix套接字连接将会被禁止。

   host

这个记录匹配通过TCP/IP的进行的连接请求。host记录匹配SSL或者非SSL的连接 注意:除非服务器带着合适的 listen_addresses 配置参数值启动,否则远程的TCP/IP将不能连接。因为缺省只监听本地回环地址localhost的TCP/IP连接。

   hostssl

这个记录匹配通过TCP/IP进行的连接请求,但是只能使用SSL加密进行连接。要用这个选项,服务器必须要支持SSL。此外,当服务器启动的时候必须通过设置将SSL启用(参阅Section 17.9获取更多信息)

   hostnossl

这个记录刚好与hostssl的逻辑相反;它只能匹配用TCP/IP但是不用SSL的连接。

   database

指定记录匹配的数据库名。值all将匹配所有的数据库。值sameuser表示如果请求连接的数据库名和用户名相同,则匹配。值samegroup表示请求的用户必须是与数据库同名的组中的成员。(samegropu是一个过时的参数但是samerole的拼写方式仍旧被接受)。值replication表示如果一个replication的连接被请求,则匹配(注意:replication连接不需要指定任何特定的数据库)。在其他情况下,这就是一个特定的 PostgreSQL 数据库的名字。我们可以通过用逗号分隔的方法声明多个数据库。一个包含数据库名的文件可以通过对在该文件前加@来声明。

   user

为这条记录声明所匹配的PostgreSQL用户。值all表示匹配所有用户。否则,它就是特定的数据库用户的名字,组名字可以通过用 + 做组名字前缀来声明.(在PostgreSQL中这些并不是用户和组的真正区别;a+标识真实的意思是:“匹配任意一个在这个角色中直接的或者间接的成员”,当角色的名字没有用a+来表示,那么它只匹配这一个角色。)多个用户名只可以可以用逗号隔开。一个包含用户名的文件可以通过对在该文件前加@来声明。

   address

声明这条记录匹配的客户端机器的地址。这个字段可以包含一个主机名、一个IP地址范围或者下面提到的特殊关键字。

一个IP地址是一个标准的CIDR 掩码长度的点分十进制的数。掩码长度表示客户端 IP 地址必须匹配的高位二进制位数。在给出的 IP 地址里,这个长度的右边的二进制位必须为零。在 IP 地址,/,和 CIDR 掩码长度之间不能有空白。

一个IP地址范围的典型例子可以用这种方法表示:172.20.143.89/32,这表示一个主机,或者用172.20.143.0/24表示一个小型网段,或者用10.6.0.0/16来表示一个大型网段。0.0.0.0/0表示所有IPV4的地,::/0表示所有IPV6的地址。要声明一个主机,给 IPv4 地址声明CIDR 掩码 32,给 IPv6 地址声明 128。在网络地址中,不要在尾部省略零点。

以IPv4 格式给出的IP地址会匹配那些拥有对应地址的IPv6 连接。例如:127.0.0.1将匹配IPV6的地址::ffff:127.0.0.1.以IPV6格式给出的地址只能匹配IPV6的连接,即使对应的地址在 IPv4-in-IPv6 范围内。请注意如果系统的C类库不支持IPV6的地址,那么所有IPV6的连接将会被拒绝。 你也可以写成all来匹配所有IP地址。samehost值将匹配该服务器自己拥有的任意一个IP地址,或者用samenet值来匹配在这个服务器连接的网段里的任意一个IP地址。 如果声明一个主机名(不是一个IP地址或者一个将要指定的一个关键字作为主机名),该名称是相对于一个客户端的IP地址反向名称解析的结果(例如:DNS解析,如果DNS被启用)。主机名不区分大小写。如果记录被匹配,那么,在这个主机上将会主机名进行正解析(例如:DNS正解析),然后检查解析的地址是否和客户端的IP地址相同。如果两者匹配,那么这个记录将被匹配。(在pg_hba.conf文件中的主机名应当是这样一个名字:客户端IP用address-to-name解析返回的结果,否则,如果这一行不匹配,有些主机名数据库上允许一个IP地址绑定多个主机名,但是当解析IP地址的时候操作系统上只返回一个主机名)

声明一个主机域可以在主机名前面加.如.example.com将匹配foo.example.com(但不匹配example.com)

在pg_hba.conf中声明了一个主机名,你应该确保这个名字能够快速的解析。它能够建立一个本地命名缓存,如nscd。并且,你也可以启用log_hostname参数来查看客户端主机名和IP地址的替换日志。

有时,用户想知道为什么要使用两个名称互相解析这种看似很复杂的方式来解析主机名,而且还有需要反向解析IP地址,并且有时候主机名没有建立或指向一些不正确的主机名。这样主要是为了提高效率:一个连接将会请求两个解析器来解析当前客户端的地址。如果这个地址的解析器有问题,那么它只是客户端的问题。假设采取另一种方式,那么它不得不去解析在pg_hba.conf中出现的每一个主机名来尝试连接。这样将非常慢。而且如果一个主机名的解析器出现问题,那么这将导致所有主机都有问题.

并且,反向查找是为了实现后缀的匹配功能,因为需要知道实际的客户端主机名,以便它能进行模式匹配。

请注意这个方法和其他流行的基于主机名的访问控制是一致的,例如,Apache的HTTP服务器和TCP Wrappers。

   此字段仅适用于主机,hostssl和hostnossl记录。
   IP-address
   IP-mask

这个可以看作是CIDR-address的补充。它不是声明掩码的长度,而是在另外一个字段里声明实际的掩码。例如,255.0.0.0 表示IPv4 CIDR 掩码长度为8,255.255.255.255表示CIDR的掩码长度为32.

   此字段仅适用于主机,hostssl和hostnossl记录。
   auth-method

声明通过这条记录联接的时候使用的认证方法。可能的选项请看下面的内容,详细的信息请参阅Section 19.3。

      trust

无条件的允许连接。这个方法允许任何人用任意一个PostgreSQL用户登录到PostgreSQL数据库。

      reject

无条件的拒绝连接。这对于过滤一个组中的某些主机非常有用,例如,一个reject的行能够阻止一个指定的主机连接。而允许特定的网络中其他主机的连接。

      md5

要求客户端提供一个MD5加密的口令进行认证。请查阅Section 19.3节获取详细的信息。

      password

要求客户提供一个未加密的密码进行身份验证。因为口令是以明文形式在网络上传递的,所以我们不应该在不安全的网络上使用这个方式。请参阅 Section 19.2.2 获取详细信息。

      krb5

使用Kerberos V5来进行认证用户。这只对TCP/IP连接有效。请参阅Section 19.3.5获取详细信息。

      ident

获取客户端的操作系统的用户名,然后联系客户端上的ident服务器并检查是否和要求的数据库用户名匹配。Ident认证只对TCP/IP连接有效。如果是本地连接,将会被peer认证方法替换。请参阅Section 19.3.6获取详细信息。

      peer

从操作系统获取操作系统的用户名,然后检查它是否和请求的数据库名相匹配。这只对本地连接有效。请参阅Section 19.3.7获取详细信息。

      ldap

用LDAP服务器进行认证,请参阅Section 19.3.8获取详细信息。

      radius

用RADIUS服务器进行认证。

      cert

用SSL客户端证书进行认证,请参阅Section 19.3.10获取详细信息。

      pam

使用操作系统提供的可插入的认证模块服务(Authenticate using the Pluggable Authentication Modules)(PAM)。请参阅Section 19.3.11 获取详细信息。

   auth-options

在auth-method这一栏之后,能够以name=value的形式为这些认证方法指定一些选项。关于这些选项的详细信息请看下面描述。

在文件中用@构造一个名字的列表,也可以用空格或者来隔开。用#号进行注释,像pg_hba.conf文件那样。也允许用@进行嵌套构造。除非文件名后面的@是一个绝对路径,否则,被当作与包含该文件的目录的相对路径

由于每个连接是顺序的检查pg_hba.conf的记录,所以记录的顺序是非常重要的。通常,靠前的记录有比较严的连接匹配参数和比较弱的认证方法,而靠后的记录有比较宽松的匹配参数和比较严的认证方法。例如,我们一般都希望对本地 TCP/IP连接使用trust认证,而对远端的TCP/IP连接要求口令。在这种情况下我们将 trust 认证方法用于来自 127.0.0.1 的连接,这条记录将出现在允许更为广泛的使用密码认证的客户端IP地址的记录的前面。

当主服务器进程(postmaster)收到SIGHUP信号启动时将会读取pg_hba.conf。如果你在正在运行的系统上编辑了这个文件,你需要发送一个信号给postmast进程(用pg_ctl reload命令或者kill -HUP)来重新读取这个文件。

      提示:要连接到一个特定的数据库,用户不仅仅需要通过pg_hba.conf文件的检查,还需要有这个数据库的CONNECT权限。如果你希望拒绝这个用户连接这个数据库,它将是非常容易控制的,用granting/revoking CONNECT来控制连接和回收连接权限,这比修改pg_hba.conf这整个文件要更容易。

在 Example 19-1里是pg_hba.conf记录的一些例子。请查看下一节获取不同认证方法的细节。

   Example 19-1. Example pg_hba.conf Entries
   # Allow any user on the local system to connect to any database with
   # any database user name using Unix-domain sockets (the default for local
   # connections).
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   local   all             all                                     trust
   
   # The same using local loopback TCP/IP connections.
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    all             all             127.0.0.1/32            trust
   
   # The same as the previous line, but using a separate netmask column
   #
   # TYPE  DATABASE        USER            IP-ADDRESS      IP-MASK             METHOD
   host    all             all             127.0.0.1       255.255.255.255     trust
   
   # The same over IPv6.
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    all             all             ::1/128                 trust
   
   # The same using a host name (would typically cover both IPv4 and IPv6).
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    all             all             localhost               trust
   
   # Allow any user from any host with IP address 192.168.93.x to connect
   # to database "postgres" as the same user name that ident reports for
   # the connection (typically the operating system user name).
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    postgres        all             192.168.93.0/24         ident
   
   # Allow any user from host 192.168.12.10 to connect to database
   # "postgres" if the user's password is correctly supplied.
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    postgres        all             192.168.12.10/32        md5
   
   # Allow any user from hosts in the example.com domain to connect to
   # any database if the user's password is correctly supplied.
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    all             all             .example.com            md5
   
   # In the absence of preceding "host" lines, these two lines will
   # reject all connections from 192.168.54.1 (since that entry will be
   # matched first), but allow Kerberos 5 connections from anywhere else
   # on the Internet.  The zero mask causes no bits of the host IP
   # address to be considered, so it matches any host.
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    all             all             192.168.54.1/32         reject
   host    all             all             0.0.0.0/0               krb5
   
   # Allow users from 192.168.x.x hosts to connect to any database, if
   # they pass the ident check.  If, for example, ident says the user is
   # "bryanh" and he requests to connect as PostgreSQL user "guest1", the
   # connection is allowed if there is an entry in pg_ident.conf for map
   # "omicron" that says "bryanh" is allowed to connect as "guest1".
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   host    all             all             192.168.0.0/16          ident map=omicron
   
   # If these are the only three lines for local connections, they will
   # allow local users to connect only to their own databases (databases
   # with the same name as their database user name) except for administrators
   # and members of role "support", who can connect to all databases.  The file
   # $PGDATA/admins contains a list of names of administrators.  Passwords
   # are required in all cases.
   #
   # TYPE  DATABASE        USER            ADDRESS                 METHOD
   local   sameuser        all                                     md5
   local   all             @admins                                 md5
   local   all             +support                                md5
   
   # The last two lines above can be combined into a single line:
   local   all             @admins,+support                        md5
   
   # The database column can also use lists and file names:
   local   db1,db2,@demodbs  all                                   md5

19.2. 用户名映射

当我们用Ident或者GSSAPI这些系统外部的认证方法,发起连接的的操作系统的用户名可能和它需要连接数据库用户名不一致,在这种情况下,操作系统的用户名和数据库的用户名需要做一个映射,用map=map-name这个选项在pg_hba.conf文件中进行声明。对于外部用户名这个选项支持所有的认证方法。由于不同的连接可能需要不同的映射,所以映射的名字需要在pg_hba.conf文件中用map-name参数进行声明,表示映射到每个特定的连接。

用户名的映射在ident映射文件中进行定义,缺省的名字叫做pg_ident.conf,存储在集群的数据目录。(然而这个映射文件也可以放在其他地方,请查看ident_file配置参数。)这个ident映射文件中的行一般是如下形式:

   map-name system-username database-username

对于注释和空白的处理和pg_hba.conf一样。map-name是一个任意的名称,在pg_hba.conf中被提到的映射它将被用到。其他两个字段声明一个操作系统的用户名和一个匹配的数据库用户名。同样的映射名称可以在一个单个的映射中声明多个用户名。

如果system-username字段用/开头,那么这个字段其余的部分将是一个正则表达式。(请参阅Section 9.7.3.1获取更详细的PostgreSQL正则表达式的语法)如果system-username字段用/开头,那么这个字段其余的部分将是一个正则表达式。(请参阅Section 9.7.3.1获取更详细的PostgreSQL正则表达式的语法)正则表达式可以捕获单个的字符或者用括号括起来的子表达式,然后可以在database-username这个字段中用\1(反斜杠后面加数字1)进行引用。进行引用。在单行中允许多个用户名映射,这是一个特别有用的简单的语法替换。例如,这些条目

   mymap   /^(.*)@mydomain\.com$      \1
   mymap   /^(.*)@otherdomain\.com$   guest

这将禁止以@mydomain.com域名结尾的系统用户和数据库用户进行连接,但是允许以@otherdomain域名结尾的系统用户用guest用户登录系统。

提示:请记住,在默认情况下,一个正则表达式只是匹配一个字符串的一部分。通常的方法是用^和$符号,上面的例子是强制匹配整个系统用户名。

当主服务器进程(postmaster)收到SIGHUP信号启动的时候pg_ident.conf文件将会被读取。如果你在活跃的系统编辑了这个文件,你将需要发送一个信号(用pg_ctl reload或者kill -HUP命令)让postmaster进程重新读取这个文件。

pg_ident.conf文件能够和在Example 19-1例子中的pg_hba.conf文件共同来工作,请看Example 19-2.在这个例子中,在192.168这个网段,除了操作系统用户名为bryanh,ann或者robert将不允许访问。Unix用户robert只允许访问PostgreSQL的bob用户,其他非robert用户将不能连接bob用户。ann只能够连接PostgreSQL的ann用户,用户bryanh将允许连接PostgreSQL的bryanh和guest1用户。

   Example 19-2. An Example pg_ident.conf File
   # MAPNAME       SYSTEM-USERNAME         PG-USERNAME
   omicron         bryanh                  bryanh
   omicron         ann                     ann
   # bob has user name robert on these machines
   omicron         robert                  bob
   # bryanh can also connect as guest1
   omicron         bryanh                  guest1

19.3. 认证方法

以下小节将描述认证方法的详细信息。


19.3.1. Trust认证

当trust认证被声明之后,PostgreSQL允许任何用户都能访问这个服务器上的这个数据库,无论数据库名是什么(甚至是超级用户)。当然,限制数据库和用户的行仍旧会生效。这个方法应当只用于在有操作系统级别保护这个数据库的情况下使用。 trust认证方法对于一个单用户工作站中的本地连接是一个很合适和方便的方法。这种方法不适合在多用户系统中使用。然而,如果你用文件系统权限限制了对服务器的Unix-domain socket访问,你也可以用trust认证方式在多用户系统中使用.要实现这些,可以设置unix_socket_permissions(或者unix_socket_group参数)参数来实现,就像在Section 18.3描述的那样。或者你也可以设置一个unix_socket_directory参数,把socket文件存放在在一个适当的限制目录里。

设置文件系统权限仅对Unix-socket连接有效。本地TCP/IP连接不能用文件系统的权限进行限制。因此,如果你用文件系统权限来保证本地连接安全,你应该在pg_hba.conf文件中移除host。。。127.0.0.1.。。这样的行,或者将这行改成不用trust进行认证。

trust认证只适合TCP/IP连接,如果你想允许每一个用户在每一台机器上都能访问,可以在pg_hba.conf文件中指定用trust认证。我们很少有理由使用除了本地连接(127.0.0.1)以外的其他TCP/IP连接使用trust认证。


19.3.2. 密码认证

基于密码的认证方式包括md5和password。这些方法操作上非常类似,只不过连接传送的方法不同,password方式是通过明文传输密码,md5方式是通过MD5加密传输密码。

如果你担心口令被窃听("sniffing"), 那么 md5方式比较合适。应该避免使用简单的密码。不过,md5方式不支持db_user_namespace特性。如果用SSL加密进行连接,那么password方式将会更加安全(然而基于SSL连接认证将会是一个不错的选择)。

PostgreSQL数据库的密码与操作系统的用户密码无关。每一个数据库用户的面貌都被存储在pg_authid系统表中。可以用SQL命令CREATE USER和ALTER USER命令进行密码管理,例如,CREATE USER foo WITH PASSWORD ‘secret’。如果用户没有设置密码,这个存储密码的字段将为空,对于这个用户,密码认证方式将会失效。


19.3.3. GSSAPI认证

GSSAPI是在RFC 2734中定义的一个安全行业安全认证标准协议。PostgreSQL支持的GSSAPI认证和在RFC 1964中定义的Kerberos认证一致。GSSAPI为系统提供并支持自动认证(单点登陆)。这个认证本身很安全,但是数据库连接中的数据传输将不会被加密,除非使用了SSL加密。

当GSSAIP使用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_realm被禁止,用户名映射的是username/hostbased,并且如果include_realm被启用,用户名映射的是username/hostbased@EXAMPLE.COM。

  krb_realm

设置一个匹配的用户名的范围。如果这个参数被设置,那么只有在这个范围内的用户能进行访问。如果没有设置,无论用户名映射是否完成,任何范围的用户都能访问,


19.3.4. SSPI认证

对于单点登录的安全认证来说SSPI是一个windows技术。PostgreSQL在negotiate模式下使用SSPI,当在其他情况下可能自动回退到用NTLM模式,这样就会使用Kerberos。

当用Kerberos认证,SSPI的工作方式和GSSAPI一致,请参阅Section 19.3.3获取详细信息。

以下是SSPI支持的配置选项:

   include_realm
 

如果这个参数设置成1,这个区域的认证用户将会通过用户名的映射加入到系统用户名中(Section 19.2)。这对于多区域内处理用户是非常有用的。

   map
  

允许系统和数据库用户名之间进行映射。请参阅Section 19.2获取更多信息。

   krb_realm

设置一个匹配的用户名的范围。如果这个参数被设置,那么只有在这个范围内的用户能进行访问。如果没有设置,无论用户名映射是否完成,任何范围的用户都能访问.


19.3.5. Kerberos认证

注意:本地Kerberos认证已经过时,仅用于向后兼容。新安装和升级安装鼓励使用行业标准GSSAPI的认证方法(请参阅Section 19.3.3)。

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

PostgreSQL支持Kerberos 5.当PostgreSQL被创建,Kerberos就能够被启用,请参阅Chapter 15获取更多信息。

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

servicename可以在服务器端用krb_srvname参数进行设置,在客户端就可以使用用krbsrvname连接参数。(另见Section 31.1。)安装的时候缺省的名字是postgres并可以用./configure --with-krb-srvnam=whatever来改变这个缺省名字。在大多数环境中这个参数需要被更改。不过,当又多个PostgreSQL在同一台主机上安装时这个参数必须要更改。有些Kerberos实现需要用不同的服务名,像微软的活动目录要求的服务名为大写(POSTGRES)。

hostname 是服务器合格的主机名字。服务器的域是服务器机器的优先域。

客户主必须用PostgreSQL数据库用户名作为第一个组件。例如pgusername@realm。另外,你也可以用用户名映射来自第一个组件的数据库的用户名。缺省情况下,PostgreSQL将不检查客户端的域。如果跨域认证被启用就需要验证这个域,用krb_realm参数或者启用include_realm,并且用用户名映射来检查这个域。

确定你的服务器密匙文件能被PostgreSQL服务器账户读取(最好是只读)。(另见Section 17.1.)这个密匙文件的位置由krb_server_keyfile配置参数来指定。缺省是在/usr/local/pgsql/etc/krb5.keytab(或者是任意目录,只要在创建的时候指定sysconfdir参数)

这个密匙文件由Kerberos软件生成,请参阅Kerberos的文档获取详细信息。以下的例子是有MIT-compatible 在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 web服务器上使用mod_auth_kerb和mod_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服务器获取客户端操作系统的用户名,然后以此判断是否允许这个数据库用户名(使用用户名映射)。这个认证方式只支持TCP/IP连接。

   注意:当用ident认证声明了一个本地连接(非TCP/IP连接),将会用peer认证方式进行替换(见Section 19.3.7)。

以下是ident支持的配置选项:

   map

允许系统和数据库用户名之间进行映射。请参阅Section 19.2获取更多信息。

在RFC 1413中有对这个认证协议的描述。事实上,实际上每个类Unix的操作系统都带着一个缺省时侦听113端口的ident服务器.这个ident服务器的基本功能是回答类似这样的问题“是什么用户从你的端口X初始化出来联接到我的端口Y上来了?”。当物理连接建立之后,PostgreSQL既知道X的值又知道Y的值。它能够询问连接的客户端主机上的ident服务器,理论上可以确定发起连接的操作系统用户。

这佯做的缺点是取决于客户端的完整性:如果这个客户端不可信的或者被破坏,那么这个破坏者可以通过113端口运行程序来获取他选择的任何一个用户。这个认证方法仅适合在封闭的网络中,每一台机器都在严密的控制下,并且数据库和系统的管理员没有密切的联系。换句话说,你必须信任运行这ident服务的机器。注意这个警告:

   这个认证协议并不打算作为授权或者访问控制协议。                                              

--RFC 1413

一些ident服务器有一个非标准的选项,使返回的用户名被加密,这个密匙只有机器的管理员知道。当ident服务使用了PostgreSQL,这个选项将不能使用,因为PostgreSQL没有办法解密这个字符串来确定真实的用户名。

19.3.7. Peer认证

peer认证的工作方式是从内核获取客户端操作系统的用户名,然后以此判断是否允许这个数据库用户名(使用用户名映射)。这个方法只支持本地连接。

以下是peer支持的配置选项:

   map

允许系统和数据库用户名之间进行映射。请参阅Section 19.2获取更多信息。

Peer认证只对系统支持SO_PEERCRED并且是Unix-domain sockets请求有效(如流行的LINUX,FreeBSD,NetBSD,OpenBSD,BSD/OS,and Solaris)。PostgreSQL通过SO_PEERCRED找出客户端连接进程的操作系统用户名。


19.3.8. LDAP认证

这个认证方法和password方式操作类似,只不过是用LDAP进行密码验证。LDAP是仅用于验证用户名/密码。因此,在用LDAP进行认证之前,用户必须已经在数据库里存在。

LDAP认证有两种管理模式。在第一种模式下,而这个节点的名字是 prefix username suffix 三个组合起来的。前缀、用户名、后缀。通常,在活动目录的环境中prefix参数用来声明cn=或者DOMAIN\。suffix用来声明在非Active Directory环境中的DN的剩余部分。

在第二种模式下,这个服务器首先用固定的用户名和密码对一个LDAP目录进行身份验证,用ldapbinduser和ldapbinddn进行声明,并且尝试登录到数据库中搜索这个用户。如果没有设置用户和密码,将会以匿名用户绑定到这个目录。这个搜索将会通过ldapbasedn参数在子树中执行,并且将尝试完全匹配在ldapsearchattribute参数中声明的属性。如果没有指定属性,将会使用uid的属性。一旦用户在此搜索中被发现,这个服务器将会断开连接,并且用客户端指定的这个用户名和密码重新验证这个目录来验证这个登录是否正确。这个方法使得装载在这个目录的用户对象显得更加灵活,但是这将导致LDAP服务器产生两个独立的连接。

以下是LDAP支持的配置选项:

   ldapserver

连接到LDAP服务器的IP或者名字。

   ldpport
  

连接到LDAP服务器的端口号。如果没指定端口,将会使用LDAP库的默认端口。

   ldaptls

设置成1将会使PostgreSQL和LDAP服务器之间采用TLS加密连接。注意,这只是对LDAP服务器的传输加密--连接的客户端仍旧将是非加密的除非客户端使用SSL。

   ldapprefix

当做一个简单的身份认证时,用DN进行身份认证时作为用户名的前缀。

   ldapsuffix

当做一个简单的身份认证时,用DN进行身份认证时作为用户名的后缀。

   ldapbinddn

当用search+bind进行认证时,用DN方式进行验证这个目录并执行搜索。

   ldapbindpasswd

当用search+bind进行认证时,用密码方式进行验证这个目录并执行搜索。

   ldapsearchattribute

当用search+bind进行认证时,指定用户名的属性进行搜索。

注意:在LDAP中常常用逗号和空格对一个DN的不同部分进行分割,也常常需要用双引号将LDAP的配置选项给引起来,例如:

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


19.3.9. RADIUS认证

这个认证方法和password方法的操作类似,只不过是用RADIUS进行密码认证。RADIUS只用于验证用户名和密码对。因此,在用RADIUS进行认证之前,用户必须已经在数据库里存在。

当用RAIDUS进行认证,访问的请求信息将会发送给RADIUS服务器。这个请求将只能用Authenticate类型,并且应该包括user name,pasword(加密的)和NAS Identifier参数。这个情况将会被服务器通过私有共享的方式加密。这个RADIUS服务器将会用访问允许(Access Accept)或者访问禁止(Access Reject)对这个服务器进行回应。这不支持RADIUS账户。

以下是RADIUS支持的配置选项

   radiusserver

连接的RADIUS服务器的名字或者IP。这个参数是必须的。

   radiussecret

跟RADIUS服务器安全的交流时采用私密共享的方式。这样要在PostgreSQL和RADIUS服务器上必须有一个相同的值。推荐这个字符串至少要有16个字符。这个参数是必须的。

注意:如果PostgreSQL创建的时候支持OpenSSL,那么这个加密载体只能使用强加密。换句话说,当跟RADIUS服务器进行传输时,只应该考虑是否是模糊的不安全的口令,如果有需要应该启用外部安全措施。

   radiusport

连接的RADIUS服务器的端口号。如果没有指定端口,那么将会用默认的1812端口。

   radiusidentifier

这个字符串可以在RADIUS请求中当做NAS鉴别符。这个参数可以被当做第二参数来识别,例如用户来尝试连接这个数据库用户,可以用这个策略在RADIUS服务器上进匹配。如果没有指定识别符,默认将会使用postgresql。


19.3.10. 证书认证

这个认证方法是通过SSL客户端证书来进行认证。因此这个方法只对SSL连接有效。当用这个方法,服务器将请求客户端提供一个有效的证书。发送给客户端的时候不会有密码提示。这个cn(通用名称)证书的属性将会和请求的数据库用户名进行比较,如果匹配,将允许。用户名映射也可以允许来自不同的数据库用户名来通过cn认证。

以下是SSL证书认证支持的选项:

   map
 允许系统和数据库用户名之间进行映射。请参阅Section 19.2获取更多信息。


19.3.9.PAM认证

这个认证方法和password的操作方法类似。只不过它是使用PAM(课插拔的认证模块)认证结构。这个默认的PAM服务名是postgresql。PAM只对用户名/密码对有效。所以在PAM认证使用前用户必须在数据库已经存在。关于PAM的更多信息,请阅读Linux-PAM Page and the Solaris PAM Page.

以下是PAM支持的配置选项:
   pamservice
    PAM服务名。

注意:如果PAM被设置成读取/etc/shadow,认证将会失败,因为PostgreSQL服务是用非root用户启动的。因此,如果采用PAM配置了LDAP或者其他的认证方法,这中模式是不能使用的。

19.4. 认证问题

认证失败或者其他的相关问题通常显示的错误信息跟以下提示的类似:

   FATAL:  no pg_hba.conf entry for host "123.123.123.123", user "andym", database "testdb"

这个信息意味着你能够成功的与服务器建立联系,但是不能得到回应。这个信息提示,服务器拒绝连接请求,因为它在整个pg_hba.conf配置文件中没有发现匹配的条件。

   FATAL:  password authentication failed for user "andym"

信息显示你能连接到这个服务器,服务器也能进行回应,但是在pg_hba.conf中指定的认证方法不能让请求通过。请检查你提供的密码,如果你使用了kerberos或者ident软件,请检查这些认证类型。

   FATAL:  user "andym" does not exist

这表示数据库用户名没有找到。

   FATAL:  database "testdb" does not exist

这表示你连接的数据库不存在。注意,如果你没有指定连接的数据库名,它将会用默认的数据库名,这可能是也可能不是正确的。

   提示:服务器的日志包含了更多关于认证失败的信息以便报告给客户端。如果你对这些提示信息感到疑惑,请检查服务器的日志。