问题现象
DataEase(v2.x)配置 PostgreSQL 数据源时报认证失败(28P01/40001 密码错误),但密码本身确认无误。
排查关键点
1. 定位方向:先确认密码本身没问题
- 用本地连接(
-U postgres)能登录 → 说明角色和密码值没问题,问题出在网络连接链路上 - 用 TCP 连接(
host=127.0.0.1)也报错 → 锁定是认证方式层面的问题,而不是密码记错
2. 查看密码存储格式
SELECT rolname, rolpassword FROM pg_authid WHERE rolname='postgres';
docker exec -it my-pg psql -U postgres -c "SHOW password_encryption;"
docker exec -it my-pg psql -U postgres -c "SELECT substring(rolpassword,1,13) AS hash_type FROM pg_shadow WHERE usename='postgres';"
md5开头 → MD5 格式SCRAM-SHA-256$开头 → SCRAM 格式
docker exec -it my-pg psql -U postgres -d demo -c “SET password_encryption=’scram-sha-256′; ALTER USER postgres WITH PASSWORD ‘vQ78cns912lcm6U’;”
ALTER ROLE
3. 查看认证规则pg_hba.conf(或 SHOW hba_file; 定位文件)中该网段的规则是 scram-sha-256,而用户密码却是 MD5 格式存储——这就是根因:
host lsfmon all 172.21.0.0/16 scram-sha-256
PostgreSQL 从 MD5 升级到 SCRAM 后,两者认证机制不兼容。服务端要求 SCRAM 握手,但库里存的 MD5 哈希无法参与 SCRAM 协商,必然认证失败。
修复方法(一条命令同时改密码和格式)
SET password_encryption='scram-sha-256';
ALTER USER postgres WITH PASSWORD '新密码';
关键点:必须先 SET 再 ALTER,否则新密码会按默认格式(可能是 md5)写入,改了也白改。
验证闭环
用和外部应用一致的连接方式(TCP + 明确指定 host/port)测试,通过后回 DataEase 重新保存密码并校验。
经验教训
| 要点 | 说明 |
|---|---|
| 密码”对”≠能登录 | 认证失败未必是密码错,还可能是哈希格式与认证规则不匹配 |
| 验证要贴近真实链路 | 本地 socket 能连 ≠ TCP 能连,hba 规则按连接类型区分 |
SET 和 ALTER 同会话执行 | password_encryption 是会话级参数,分开会话可能不生效 |
| 环境迁移/升级后重点检查 | PG 版本升级、容器重建、pg_hba 变更后,老用户密码格式容易遗留 md5 |
| 长期建议 | 统一 pg_hba 为 scram-sha-256,避免混用留坑 |
核心一句话:认证失败先查三方一致性——客户端驱动、pg_hba 规则、密码存储格式,三者必须匹配。