@H_
502_0@当一个客户端应用与
数据库服务器进行联接时,它声明 它将以哪个 Postgre
sql 用户的
名称进行联接, 就象我们
登录一台 Unix 计算机 一样.在
sql 环境里,活跃的
数据库用户名决定
数据库对象的各种访问。因此, 实际上我们要限制的是
用户可以联接的
数据库;
@H_
502_0@认证 是
数据库服务器建立客户端应用的标识, 然后通过一些手段判断是否允许此客户端应用(或者运行这个客户端应用的
用户)与它所要求的
用户名进行联接的过程;
@H_
502_0@Postgre
sql 提供多种不同的客户端认证方式.认证某个特定客户端联接所使用的
方法可以通过基于 (客户端)的主机地址,
数据库和
用户的方式进行选择; 一些认证
方法还允许你通过
用户名进行限制;
@H_
502_0@Postgre
sql 用户名在逻辑上是和服务器运行的操作系统
用户名相互独立的. 如果某个服务器的所有
用户在那台服务器机器上也有帐号, 那么给
数据库用户赋与操作系统
用户名是有意义的.不过, 一个接收远程访问的服务器很有可能有许多没有本地帐号的
用户, 因而在这种情况下
数据库用户和操作系统
用户名之间不必有任何联系;
@H_
502_0@1. pg_hba.conf
文件;
@H_
502_0@客户端认证是由数据目录里的
文件pg_hba.conf 控制的,比如: /etc/postgre
sql/8.2/main/pg_hba.conf (hba 的意思是 host-based authentication:基于主机的认证.) 在initdb初始化数据目录的时候,它会安装一个缺省的
文件;
@H_
502_0@
文件 pg_hba.conf 的常用格式是一套记录, 每行一条。空白行行被忽略,井号( "#" )开头的注释 也被忽略。一条记录是由若干用空格和/或 tab 分隔的字段组成。 如果字段用引号包围,那么它可以包含空白.记录不能夸行存在;
@H_
502_0@每条记录声明一种联接类型,一个客户端 IP 地址范围 (如果和联接类型相关的话),一个
数据库名,一个
用户名字, 以及对匹配这些参数的联接使用的认证
方法. 匹配联接类型,客户端地址和联接企图请求的
数据库名和
用户名的第一条记录 将用于执行认证.这个处理过程没有"跨越"或者 "回头"的说法∶如果选择了一条记录而且认证失败,那么 将不考虑后面的记录.如果没有匹配的记录,那么访问将被拒绝.
@H_
502_0@每条记录可以下面三种格式之一:
@H_
502_0@local database user authentication-method [authentication-option]
@H_
502_0@host database user IP-address IP-mask authentication-method [authentication-option]
@H_
502_0@hostssl database user IP-address IP-mask authentication-method [authentication-option]
@H_
502_0@1.1 各个字段的含义;
@H_
502_0@
@H_
502_0@local
@H_
502_0@这条记录匹配通过 Unix 域
套接字进行的联接企图. 没有这种类型的记录,就不允许 Unix 域
套接字的联接。
@H_
502_0@host
@H_
502_0@这条记录匹配通过 TCP/IP 网络进行的联接尝试.请注意,除非服务器是 带着 -i 选项或者打开了 postgre
sql.conf 里面的 tcpip_socket 配置参数集启动的,否则 TCP/IP 联接是被
禁止掉的.
@H_
502_0@hostssl
@H_
502_0@这条记录匹配通过在 TCP/IP 上进行的 SSL 联接企图. host 记录可以匹配 SSL 和非 SSL 的联接企图, 但 hostssl 记录需要 SSL 联接。
@H_
502_0@要使用这个选项,制作服务器的时候必须打开 SSL
支持.而且在服务器启动的时候, 必须打开在postgre
sql.conf里的ssl选项。
@H_
502_0@database
@H_
502_0@声明记录所匹配的
数据库。值 all 表明该记录匹配所有
数据库, 值 sameuser表示如果被请求的
数据库和请求的
用户同名,则匹配。 samegroup 表示请求的
用户必须是一个与
数据库同名的组中的成员。 在其他情况里,这就是一个特定的 Postgre
sql 的名字。 我们可以通过用逗号分隔的
方法声明多个
数据库。 一个包含
数据库名的
文件可以 通过对该
文件前缀 @ 来声明.该
文件必需和 pg_hba.conf 在同一个目录;
@H_
502_0@user
@H_
502_0@为这条记录声明所匹配的Postgre
sql用户.值 all 表明它匹配 于所有
用户.否则,它就是特定 Postgre
sql 用户的名字.多个
用户名可以通过用逗号分隔的
方法声明.组名字 可以通过用 + 做组名字前缀来声明.一个包含
用户名的
文件可以 通过在
文件名前面前缀 @ 来声明.该
文件必需和 pg_hba.conf 在同一个目录;
@H_
502_0@IP-address
@H_
502_0@
@H_
502_0@IP-mask
@H_
502_0@这两个字段包含标准的点分十进制表示的 IP地址/掩码值。 (IP地址只能用数字的方式声明,而不能用域名或者主机名。) 它们俩放在一起,声明了这条记录匹配的客户机的 IP 地址。 准确的逻辑是
@H_
502_0@(actual-IP-address xor IP-address-field) and IP-mask-field
@H_
502_0@对于要匹配的记录必需为零. (当然,IP地址是可以欺骗的,但是这个考虑在 Postgre
sql 的范围之外。)
@H_
502_0@这些域只适用于 host 和 hostssl 记录;
@H_
502_0@1.2 authentication-method(认证
方法);
@H_
502_0@
@H_
502_0@trust
@H_
502_0@无条件地允许联接.这个
方法允许任何可以与Postgre
sql 数据库联接的
用户以他们期望的任意 Postgre
sql 数据库用户身份进行联接,而不需要口令。
@H_
502_0@reject
@H_
502_0@联接无条件拒绝.常用于从一个组中"过滤"某些主机.
@H_
502_0@md5
@H_
502_0@要求客户端提供一个 MD5 加密的口令进行认证. 这个
方法是允许加密口令存储在pg_shadow里的唯一的一个
方法.
@H_
502_0@crypt
@H_
502_0@类似 md5
方法,只是用的是老式的 crypt 加密认证, 用于 7.2 以前的客户端.对于 7.2 以及以后的客户端,我们建议使用 md5.
@H_
502_0@password
@H_
502_0@和"md5"一样,但是口令是以明文形式在网络
上传递的. 我们不应该在不安全的网络上使用这个方式;
@H_
502_0@krb4
@H_
502_0@用 Kerberos V4 认证
用户.只有在进行 TCP/IP 联接的时候才能用;
@H_
502_0@krb5
@H_
502_0@用 Kerberos V5 认证
用户.只有在进行 TCP/IP 联接的时候才能用;
@H_
502_0@ident
@H_
502_0@
获取客户的操作系统名(对于 TCP/IP 联接,
用户的身份是通过与运行在客户端上的 ident 服务器联接进行判断的,对于本地联接,它是从操作系统
获取的。) 然后检查一下,看看
用户是否允许以要求的
数据库用户进行联接,
方法是参照在 ident 关键字后面声明的映射;
@H_
502_0@如果你使用了 sameuser 映射,那么假设
用户名 是相等的。如果没有声明这个关键字,则在与 pg_hba.conf 同目录的 pg_ident.conf
文件中找出映射名。如果这个
文件里包含一条记录标识着ident提供的
用户名 和请求的 Postgre
sql 用户名的映射, 那么联接被接受;
@H_
502_0@对于本地联接,只有在系统
支持Unix域
套接字信任证的情况下 才能使用(目前是 Linux, FreeBSD, NetBSD, OpenBSD, 和 BSD/OS);
@H_
502_0@pam
@H_
502_0@使用操作系统提供的可插入的认证模块服务 (Pluggable Authentication Modules) (PAM)来认证;
@H_
502_0@
@H_
502_0@1.3 示例;
@H_
502_0@因为认证时系统是为每个联接请求顺序检查 pg_hba.conf 里的记录的,所以这些记录的顺序 是非常关键的.通常,靠前的记录有比较严的联接匹配参数和比较弱的 认证
方法,而靠后的记录有比较松的匹配参数和比较严的认证
方法. 比如,我们一般都希望对本地 TCP 联接使用 trust 认证, 而对远端的 TCP 联接要求口令.在这种情况下我们将 trust 认证
方法用于来自 127.0.0.1 的联接,这条记录将出现在 允许更广泛的客户端 IP 地址的使用口令认证的记录前面;
@H_
502_0@注: 不要
禁止超级
用户访问 template1
数据库。各种工具命令都 需要访问 template1;
@H_
502_0@在启动和 postmaster 收到SIGHUP 信号的时候, 系统都会重新装载 pg_hba.conf
文件. 如果你在活跃的系统上编辑了该
文件,你就需要用 kill 向 postmaster 发一个 SIGHUP信号,好让它重新读取该
文件;
@H_
502_0@下面是 pg_hba.conf 的一个例子:
@H_
502_0@# 允许在本机上的任何
用户使用 Unix 域
套接字(本地连接的缺省)
@H_
502_0@# 以任何身份联接任何
数据库
@H_
502_0@#
@H_
502_0@#
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@local all all trust
@H_
502_0@# 和上面相同,但是使用的是自环的(loopback)TCP/IP 连接
@H_
502_0@#
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@host all all 127.0.0.1 255.255.255.255 trust
@H_
502_0@# 同样,但用的是 Unix-
套接字联接
@H_
502_0@local all all trust
@H_
502_0@# 允许 IP 地址为 192.168.93.x 的任何主机与
数据库
@H_
502_0@# "template1" 相连,用与他们在自己的主机上相同 ident 的
用户名标识他自己
@H_
502_0@# (通常是他的 Unix
用户名)
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@host template1 all 192.168.93.0 255.255.255.0 ident sameuser
@H_
502_0@# 允许来自主机 192.168.12.10 的
用户与 "template1"
数据库联接,
@H_
502_0@# 只要该
用户提供了在正确的口令.
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@host template1 all 192.168.12.10 255.255.255.255 md5
@H_
502_0@# 如果前面没有其它 "host" 行,那么下面两行将拒绝所有来自
@H_
502_0@# 192.168.54.1 的联接请求 (因为前面的记录先匹配
@H_
502_0@# 但是允许来自互联网上其它任何地方的有效的 Kerberos V5 认证的联接
@H_
502_0@# 零掩码表示不考虑主机 IP 的任何位.因此它匹配任何主机:
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@host all all 192.168.54.1 255.255.255.255 reject
@H_
502_0@host all all 0.0.0.0 0.0.0.0 krb5
@H_
502_0@# 允许来自 192.168.x.x 的任何
用户与任意
数据库联接,只要他们通过 ident 检查
@H_
502_0@# 但如果 ident 说该
用户是 "bryanh" 而他要求以 Postgre
sql 用户 "guest1" 联接,
@H_
502_0@# 那么只有在 `pg_ident.conf' 里有 "omicron" 的映射,说 "bryanh" 允许以
@H_
502_0@# "guest1" 进行联接时才真正可以进行联接.
@H_
502_0@#
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@host all all 192.168.0.0 255.255.0.0 ident omicron
@H_
502_0@# 如果下面是用于本地联接的仅有的三行,那么它们将允许本地
用户
@H_
502_0@# 只和它们自己的
数据库联接(
数据库名和
用户名同名),
@H_
502_0@# 只有
管理员和组"support"里的成员例外,他们可以联接到任何
数据库。
@H_
502_0@#
文件 $PGDATA/admins 列出了那些允许与所有
数据库联接的
用户名.
@H_
502_0@# 在所有情况下都需要口令。
@H_
502_0@# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
@H_
502_0@local sameuser all md5
@H_
502_0@local all @admins md5
@H_
502_0@local all +support md5
@H_
502_0@# 上面最后两行可以合起来写成一行
@H_
502_0@local all @admins,+support md5
@H_
502_0@#
数据库字段也可以使用列表和
文件名,但组不行:
@H_
502_0@local db1,db2,@demodbs all md5
@H_
502_0@
@H_
502_0@2. 认证
方法;
@H_
502_0@
@H_
502_0@2.1. 信任认证;
@H_
502_0@如果声明了 trust (信任)认证模式, Postgre
sql 就假设任何可以联接到 服务器的人都可以以任何他声明的
数据库用户(
包括数据库超级
用户) 这个
方法应该用于那些在联接到服务器端口已经有足够系统层次保护 的环境里;
@H_
502_0@trust 认证对于单
用户工作站的本地联接是非常合适和方便的. 通常它本身并不适用于多
用户环境的机器. 不过,即使在多
用户的机器上,你也可以使用 trust, 只要你利用
文件系统权限限制了对 postmaster 的
套接字
文件的访问. 要做这些限制,你可以设置 postgre
sql.conf 里面的 参数 unix_socket_permissions (以及可能还有 unix_socket_group).或者你可以 设置 unix_socket_directory,把
套接字
文件放在 一个经过恰当限制的目录里;
@H_
502_0@设置
文件系统权限只能帮助 Unix
套接字联接.它不会限制本地 TCP 联接; 因此,如果你想利用权限来控制本地安全,那么
删除 pg_hba.conf 里的 host ... 127.0.0.1 ... 行,或者把它改为一个 非 trust 的认证
方法;
@H_
502_0@trust 认证模式只有在你信任那些在 pg_hba.conf 里声明为 trust,允许联接到服务器的行上的所有机器 上面的所有
用户的时候才是合适的.很少有理由使用 trust 作为任何除来自localhost(127.0.0.1) 以外的 TCP 联接的认证方式;
@H_
502_0@2.2. 口令认证;
@H_
502_0@以口令为基础的认证
方法包括 md5,crypt, 和 password.这些
方法操作上非常类似,只不过口令通过 联接传送的
方法不同.如果你担心口令被窃听("sniffing"), 那么 md5 比较合适,如果你必需
支持 7.2 以前的老的客户端, 那么可以选 crypt.如果我们在开放的互联网上使用, 应该尽可能避免使用 password(除非你在联接上使用了 SSL, SSH,或者其他通讯安全的联接封装;
@H_
502_0@Postgre
sql 数据库口令与任何操作系统
用户口令无关. 各个
数据库用户的口令是存储在pg_shadow系统表里面的. 口令可以用
查询语言命令CREATE USER 和ALTER USER 等管理,也就是说, CREATE USER foo WITH PASSWORD 'secret';.缺省时,如果没有明确地设置口令,存储的口令是 空并且该
用户的口令认证总会失败;
@H_
502_0@要限制允许访问某
数据库的
用户集,在 一个独立的
文件里列出
用户,
用户之间用逗号分隔. 该
文件应该包含逗号分隔的
用户名或者每个
用户名一行,并且和 pg_hba.conf 在同一行. 在
用户列中写该
文件的(本)名(不带路径), 并且加一个前缀 @.
数据库名字列也类似 这样接受一列数值或者一个
文件名.你也可以通过在组名字前面 前缀 + 来声明一个组名;
@H_
502_0@2.3. Kerberos 认证;
@H_
502_0@Kerberos 是一种适用于在公共网络上进行分布计算的工业标准的安全 认证系统. 对 Kerberos 系统的叙述远远的超出了本文档的范围; 概括说来它是相当复杂(同样也相当强大)的系统. Kerberos FAQ 或 MIT 雅典娜计划是个开始探索 的好地方.现存在好几种Kerberos发布的源
代码;
@H_
502_0@要使用 Kerberos,对它的
支持必须在制作的时候打开. Kerberos 4 和 5 都被
支持, 不过我们在一次制作中只能
支持一个版本;
@H_
502_0@Postgre
sql 运行时象一个普通的 Kerberos 服务. 服务主的名字是 servicename/hostname@realm, 这里的 servicename 是 postgres (除非在配置时用 ./configure --with-krb-srvnam=whatever 选择了一个不同的 hostname. hostname 是服务器及其全称的域名字. 服务器的域是服务器机器的优先域;
@H_
502_0@客户主自给必须用它们自己的 Postgre
sql 用户名作为第一个部件,比如 pgusername/otherstuff@realm. 目前 Postgre
sql 没有检查客户的域;因此如果你打开了跨域的认证,那么在任意域里任何可以和你通讯的主都会被接受;
@H_
502_0@确认你的服务器的密钥
文件是可以被 Postgre
sql服务器帐户读取(最好就是只读的).密钥
文件( keytab)的位置是 用运行时配置参数 krb_server_keyfile 声明的;
@H_
502_0@要
生成密钥
文件(keytab),可以用下面例子(对版本5)
@H_
502_0@kadmin% ank -randkey postgres/server.my.domain.org
@H_
502_0@kadmin% ktadd -k krb5.keytab postgres/server.my.domain.org
@H_
502_0@阅读 Kerberos 的文档
获取详细信息;
@H_
502_0@在和
数据库联接的时候,请确保自己对每个主都拥有一张匹配所请求的
数据库 用户名的门票.例子∶对于
数据库用户 fred, 主 fred@EXAMPLE.COM 和 fred/users.example.com@EXAMPLE.COM 都可以用于与
数据库服务器认证;
@H_
502_0@如果你在你的Apache web 服务器上使用了mod_auth_krb和 mod_perl, 你可以用一个mod_perl脚本进行 AuthType KerberosV5SaveCredentials. 这样就有了一个通过 web 的安全
数据库访问,不需要额外的口令;
@H_
502_0@2.4. 基于 Ident 的认证;
@H_
502_0@身份(ident)认证
方法的运做模式是使用一个映射
文件列出许可的
用户 和对应的
用户的配对,然后通过检查客户端的操作系统
用户名 以及判断许可的
数据库用户名的
方法来认证。判断客户端的
用户名 是非常关键的安全点,根据连接类型的不同,它的
实现方法也略有不同;
@H_
502_0@2.4.1. 透过 TCP/IP 的身份认证
@H_
502_0@"Identification Protocol(标识协议)"在 RFC 1413 里面描述.实际上每个类Unix的操作系统 都带着一个缺省时侦听113端口的身份服务器. 身份服务器的基本
功能是回答类似这样的问题: "是什么
用户从你的端口X初始化出来 联接到我的端口Y上来了?". 因为在建立起物理联接后,Postgre
sql 既知道 X 也知道 Y,因此它可以询问 运行尝试联接的客户端的主机,并且理论上可以用这个
方法判断 发起联接的操作系统
用户;
@H_
502_0@这样做的缺点是它取决于客户端的完整性:如果客户端不可信 或者被攻击者攻破,而且它们可以在113端口上运行任何程序并且 返回他们选择的任何
用户的话,就无法认证了. 因此这个认证
方法只适用于封闭的网络,这样的网络里的每台客户机 都处于严密的控制下并且
数据库和操作系统
管理员可以比较方便地 联系上.换句话说,你必须信任运行身份(ident)服务的机器.下面是警告:
@H_
502_0@身份标识协议并不适用于认证或者访问控制协议.
@H_
502_0@--RFC 1413
@H_
502_0@
@H_
502_0@2.4.2. 透过本地
套接字的身份认证;
@H_
502_0@在
支持用于 Unix 域
套接字的SO_PEERCRED请求的系统上, (目前是 Linux, FreeBSD, NetBSD, 和 BSD/OS), 身份认证也可以用于局部联接.这个时候,使用身份认证不会
增加 安全风险;实际上这也是在这种系统上使用本地联接时的优选
方法;
@H_
502_0@在没有 SO_PEERCRED 请求的系统上,身份认证只能 通过TCP/IP连接
获取。如果需要绕开这个限制,我们可以声明 localhost 地址 127.0.0.1,然后让连接指向这个地址;
@H_
502_0@2.4.3. Ident 映射;
@H_
502_0@当使用以身份为基础的认证时,在判断了初始化联接的操作系统
用户 的名字后,Postgre
sql 判断他是否可以以 他所请求的
数据库用户的身份联接. 这个判断是由跟在pg_hba.conf
文件里的 ident 关键字后面的身份映射控制的. 有一个预定义的身份映射是sameuser,表示任何 操作系统
用户都可以以同名
数据库用户进行联接(如果后者存在的 话).其他映射必须手工创建;
@H_
502_0@非 sameuser 的身份映射存放在数据目录的
文件 里.每行的格式通常是:
@H_
502_0@map-name ident-username database-username
@H_
502_0@注释和空白和普通情况一样处理.map-name 是将用于 在pg_hba.conf里引用这个映射的任意
名称. 另外两个域声明某个操作系统
用户被允许以哪个
数据库用户的身份 进行联接.同一个map-name 可以重复用于在一个映射里声明 更多的
用户映射.对一个操作系统
用户可以映射为多少个
数据库用户没有 限制,反之亦然;
@H_
502_0@在系统启动和 postmaster 收到一个 SIGHUP 信号的时候会读取 pg_ident.conf
文件;如果你在一台活跃的系统上 编辑该
文件,那么你需要给 postmaster 发信号 (用 pg_ctl reload 或者 kill -HUP) 令其重新读取该
文件;
@H_
502_0@2.5 一个 pg_ident.conf
文件例子;
@H_
502_0@
@H_
502_0@# MAPNAME IDENT-USERNAME PG-USERNAME
@H_
502_0@omicron bryanh bryanh
@H_
502_0@omicron ann ann
@H_
502_0@# bob 在这台机器上的
用户名是 robert
@H_
502_0@omicron robert bob
@H_
502_0@# bryanh 也可以以 guest1 身份连接
@H_
502_0@omicron bryanh guest1
@H_
502_0@
@H_
502_0@2.6 PAM 认证;
@H_
502_0@这个认证类型操作起来类似 password, 只不过它使用 PAM(Pluggable Authentication Modules)作为 认证机制。缺省的 PAM 服务名是 postgre
sql。 你可以在 pam 关键字后面提供自己的可选服务名。
@H_
502_0@3. 认证问题;
@H_
502_0@真正的认证失败以及相关的问题通常由类似下面的
错误信息 表白自身;
@H_
502_0@No pg_hba.conf entry for host 123.123.123.123,user andym,database testdb
@H_
502_0@这条信息出现的最大可能是你已经联接了服务器,但她不愿意和你说话. 就象信息自己表示的那样,服务器拒绝了联接请求,因为她没有在她的 pg_hba.conf
配置文件里找到认证记录;
@H_
502_0@
@H_
502_0@Password authentication
Failed for user 'andym'
@H_
502_0@这样的信息表示你联接了服务器,并且她也愿意和你交谈,但是 你必须通过pg_hba.conf
文件里声明的 认证
方法.检查你提交的口令,或者如果
错误信息提到 这些 Kerberos 或 IDENT 认证类型时 检查你的这些软件;
@H_
502_0@
@H_
502_0@FATAL 1: user "andym" does not exist
@H_
502_0@这是表示此
用户不存在的另一
方法;
@H_
502_0@
@H_
502_0@FATAL 1: Database "testdb" does not exist in the system catalog.
@H_
502_0@你试图联接的
数据库不存在.请注意如果你没有声明
数据库名,缺省 是
数据库用户名,这可能正确也可能不正确;
@H_
502_0@请注意服务器日志可能包含比报告给客户端的更多的 有关认证失败的信息.如果你被失败的原因搞糊涂了,那么请检查日志。
原文链接:https://www.f2er.com/postgresql/197424.html