Node.js连接升级至10.2的Heroku Postgres数据库失败求助
这个问题我之前帮同事排查过类似的,核心原因是Heroku Postgres 10.2版本对SSL连接的安全标准做了升级,而你用的pg 7.4.2 npm包默认的SSL配置已经跟不上这个要求了,才会触发那个TLS层的断言错误。
下面给你几个可行的解决方案,按优先级排序:
1. 临时快速修复(先确保能连上)
不要只依赖连接字符串里的?ssl=true,手动给Pool/Client添加SSL配置项,关闭证书验证(注意这是临时方案,后面建议换成更安全的方式):
const { Pool } = require('pg'); // 替换成你的连接字符串,或者直接用环境变量 const pool = new Pool({ connectionString: '你的Heroku Postgres连接字符串', ssl: { rejectUnauthorized: false } });
为什么这么做?因为pg 7.4.2默认会尝试严格验证服务器证书,但Heroku Postgres的证书链可能和旧版本pg内置的CA根证书不匹配,关闭这个验证就能绕开当前的TLS握手错误。
2. 安全持久化方案(推荐)
如果想要保持连接的安全性,需要手动配置Heroku Postgres对应的CA根证书:
- 首先,创建一个
rootCA.pem文件,把以下证书内容复制进去:
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
- 然后修改Pool/Client的配置,添加CA证书验证:
const fs = require('fs'); const { Pool } = require('pg'); const pool = new Pool({ connectionString: process.env.DATABASE_URL, // 推荐用环境变量管理连接字符串 ssl: { rejectUnauthorized: true, ca: fs.readFileSync('./rootCA.pem').toString() } });
这个证书是Heroku Postgres使用的DigiCert Global Root CA,配置后就能完成合法的证书验证,同时解决TLS握手的问题。
3. 长期方案:升级pg包
如果你的项目允许,建议把pg包升级到最新稳定版本(比如v8+),新版本的pg已经默认适配了Heroku Postgres的SSL要求,不需要额外配置就能正常连接,而且还能获得更多功能和安全补丁。升级命令很简单:
npm install pg@latest
补充说明
之前你用?ssl=true能正常连接,是因为旧版本的Heroku Postgres允许较宽松的TLS协议和证书验证,而升级到10.2后收紧了安全策略,旧版pg的默认配置不再满足要求,所以手动指定SSL参数是关键。
内容的提问来源于stack exchange,提问作者647er

