3. 身份认证机制与配置实战

PostgreSQL 的连接认证由 pg_hba.conf 统一裁决。客户端发起连接时,后端进程按文件自上而下逐行匹配,一旦命中第一条符合“连接类型 + 数据库 + 用户 + 来源地址”的记录,就采用该行指定的认证方法,不再继续向下查找。理解这个“首行命中即停止”的规则,是排查认证问题的第一原则。

pg_hba.conf 的字段结构与匹配逻辑

每条规则由五个基本字段构成:连接类型、数据库、用户、来源地址、认证方法,后面可跟认证选项。连接类型常见取值有 local(Unix 域套接字)、host(TCP/IP,含 SSL 与非 SSL)、hostssl(仅 SSL 加密连接)、hostnossl(仅非加密连接)。数据库和用户字段可写具体名称、逗号分隔列表,或 all;用户字段还可用 +角色名 引用角色成员。来源地址支持 CIDR 网段、单独 IP,或用 samehost、samenet 等关键字。

下面是一份典型的生产环境片段,先放行本机管理,再允许内网应用以密码认证,最后拒绝其余来源:

# TYPE   DATABASE   USER      ADDRESS         METHOD
local    all        postgres                  peer
host     all        dba       10.0.0.0/24     scram-sha-256
hostssl  appdb      appuser   10.10.0.0/16    scram-sha-256
host     all        all       0.0.0.0/0       reject

注意最后一行 reject 的作用:它显式拒绝所有未匹配来源,避免默认放行带来的风险。修改后必须执行 SELECT pg_reload_conf(); 或 pg_ctl reload 使配置生效,无需重启实例。若某条规则写错,可用 psql -h 主机 -U 用户 -d 库名 复现连接,观察返回的 FATAL: no pg_hba.conf entry for host ... 或 password authentication failed 来定位是匹配失败还是密码校验失败。

密码加密方式:从 md5 到 scram-sha-256

PostgreSQL 支持 password(明文传输,仅建议配合 SSL)、md5 和 scram-sha-256 三种密码类方法。md5 在服务端存储的是 md5(密码+用户名) 的哈希,且握手过程可被离线暴力破解;scram-sha-256 采用加盐挑战应答,服务端不存储可直接重放的凭据,是当前推荐方案。

启用 scram 需要两步:先在 postgresql.conf 中设置 password_encryption = scram-sha-256,再重置用户密码使其以新算法存储:

ALTER SYSTEM SET password_encryption = 'scram-sha-256';
SELECT pg_reload_conf();
ALTER USER appuser WITH PASSWORD 'Str0ng_P@ss';
-- 查看存储格式:SCRAM-SHA-256$4096:...
SELECT rolname, substring(rolpassword,1,20) FROM pg_authid WHERE rolname='appuser';

若旧用户仍是 md5 哈希,认证会失败并提示 password authentication failed,此时需重新设置密码。迁移期间可临时保留 md5 规则,但应尽快完成全量切换。

LDAP、GSSAPI 与证书认证

企业环境常把认证委托给目录服务。LDAP 认证通过 ldapserver、ldapbasedn、ldapprefix/ldapsuffix 等参数拼接用户 DN 并绑定验证:

host  all  all  10.0.0.0/24  ldap  ldapserver=ldap.corp.example \
      ldapbasedn="ou=people,dc=corp,dc=example" \
      ldapprefix="uid=" ldapsuffix=",ou=people,dc=corp,dc=example"

GSSAPI(Kerberos)适合已部署域控的环境,客户端用 kinit 获取票据后即可免密登录,服务端需有对应 krb5.keytab 与 SPN。证书认证则用 cert 方法,要求客户端提供由受信 CA 签发的证书,并通过 clientcert=verify-full 校验 CN 与数据库用户名一致,实现“证书即身份”。

多因素认证集成

PostgreSQL 本身不内置 MFA,但可通过组合规则实现。常见做法是:hostssl + cert 作为第一因素(持有证书),再叠加 scram-sha-256 作为第二因素(知道密码)。由于 pg_hba 一行只能指定一种方法,实际落地通常借助 PAM:在 pg_hba.conf 写 pam 方法,由 PAM 模块串联 pam_google_authenticator 等实现动态口令,从而在数据库层完成双因素校验。

pg_hba.conf 认证匹配与多因素集成路径 客户端连接 psql / 应用驱动 逐行匹配 pg_hba 类型·库·用户·地址 首行命中即停止 scram-sha-256 加盐挑战应答 LDAP / GSSAPI 目录 / Kerberos 票据 cert 证书认证 CA 签发 + CN 校验 多因素集成 cert + scram 或 PAM 动态口令 双因素校验 认证结果判定 成功 → 建立会话;失败 → FATAL 日志定位匹配行或密码校验 修改后 pg_reload_conf() 热加载,无需重启 关键原则:规则自上而下匹配,首条命中生效;生产环境末尾显式 reject; 密码优先 scram-sha-256,敏感链路用 hostssl,高安全场景叠加证书或 PAM 实现 MFA。

实战排查与配置要点

认证失败时,先看服务端日志中的 FATAL 行:若提示 no pg_hba.conf entry,说明没有规则匹配到该来源或用户,需要补充规则;若提示 password authentication failed,说明规则已命中但凭据校验未通过,应检查密码算法是否一致、LDAP 绑定 DN 是否正确、证书 CN 是否与用户名匹配。可用 SHOW password_encryption; 确认当前加密方式,用 SELECT * FROM pg_hba_file_rules;(PostgreSQL 10+)直接查看已加载规则及其行号,快速核对顺序。

建议把 pg_hba.conf 纳入版本管理,每次变更记录“规则行、目的、生效时间”,并在变更后用 psql 从不同网段各测一次,确认放行与拒绝都符合预期。
切勿在公网直接使用 host all all 0.0.0.0/0 trust;trust 表示完全信任来源,任何能连到端口的客户端都可免密登录,等同于关闭认证。

综合来看,一套稳健的认证配置应遵循“最小放行、加密优先、分层验证”的思路:本机管理用 peer,内网应用用 scram-sha-256 并强制 hostssl,跨域或高安全场景引入 LDAP、GSSAPI 或证书,必要时通过 PAM 叠加动态口令形成多因素。掌握匹配顺序与各方法的适用边界,就能在可用性与安全性之间取得平衡。