使用pgx驱动连接PostgreSQL失败但终端psql可正常连接
问题表现
代码运行报错
使用pgx v4驱动编写的Go程序连接PostgreSQL时抛出如下错误:
2022/06/21 16:01:07 Failed to connect to db: failed to connect to 'host=localhost user=postgres database=local': server error (FATAL: Ident authentication failed for user "postgres" (SQLSTATE 28000)) exit status 1
对应代码实现:
import ( "context" "log" "github.com/jackc/pgx/v4" ) func main() { dbCtx := context.Background() db, err := pgx.Connect( dbCtx, "postgres://postgres:smashthestate@localhost:5432/local", ) if err != nil { log.Fatalf("Failed to connect to db: %v\n", err) } defer db.Close(dbCtx) // 后续数据库操作 }
终端连接表现
使用相同用户名、库名参数执行psql命令可正常连接,执行查询无报错,测试命令如下:
psql -d local -U postgres -W -c 'select * from interest;'
该命令使用非root、非postgres的普通系统用户执行也可正常运行。
已知配置
pg_hba.conf中已配置本地Unix套接字连接的认证方式为trust:
local all all trust
问题根因
两种连接方式使用的底层连接协议不同,匹配的pg_hba.conf认证规则完全不一致:
- 执行psql命令时未指定
-h参数,客户端默认通过Unix域套接字连接数据库,正好匹配前缀为local的套接字连接规则,也就是配置的trust认证,因此不需要密码校验、不限制系统用户即可正常连接。 - Go代码里的连接串明确指定主机地址为
localhost,pgx驱动会默认通过TCP/IP协议连接本地5432端口,这类连接不会匹配local前缀的规则,只会匹配pg_hba.conf中前缀为host/hostssl/hostnossl的TCP连接规则。默认安装的PostgreSQL中,本地TCP连接的认证规则通常配置为ident,因此会抛出Ident认证失败的错误。
修复方案
二选一即可:
- 方案1:修改连接串走Unix域套接字
将连接串中的localhost:5432替换为PostgreSQL的Unix套接字路径(默认路径通常为/var/run/postgresql,部分发行版为/tmp,可通过show unix_socket_directories;查询确认),修改后的连接串示例:
修改后驱动将通过Unix套接字连接,匹配已配置的trust规则。postgres://postgres:smashthestate@/local?host=/var/run/postgresql - 方案2:修改TCP连接的认证规则
编辑pg_hba.conf,找到本地IPv4、IPv6的TCP连接配置行,将认证方式从ident改为和数据库密码加密方式匹配的密码认证(当前新版本PostgreSQL默认加密方式为scram-sha-256,旧版本为md5),配置示例:
保存后执行host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256pg_ctl reload重载数据库配置即可生效,之后TCP连接会校验连接串中的密码,认证通过即可正常连接。
内容的提问来源于stack exchange,提问作者mcv_dev
相关产品推荐
相关产品推荐

