Node.js 请求测试环境失败报 UNABLE_TO_GET_ISSUER_CERT_LOCALLY,是因为其默认仅信任内置 Mozilla CA 列表,不自动加载系统证书库;访问企业私有 CA 签发的 HTTPS 服务时,因根证书未注入而校验失败。

Node.js 请求测试环境失败,报 UNABLE_TO_GET_ISSUER_CERT_LOCALLY,基本就是 CA 证书链缺失或不被信任,不是网络不通、也不是代码写错。
为什么 Node.js 会卡在“找不到颁发者证书”
Node.js 默认只信任内置的 Mozilla CA 列表(ca-store),它不自动读取系统证书库(比如 macOS Keychain 或 Windows Cert Store)。当你访问内部测试域名(如 api.dev.example.com)时,如果该服务用的是公司私有 CA 签发的证书,Node.js 就没法验证其签发链——因为根证书没加载进来。
常见触发场景:
- 企业内网 HTTPS 接口返回 500 或连接被重置,但浏览器能正常打开(浏览器复用了系统信任库)
- 本地用
fetch/axios/https.request调用测试环境 API 时抛出UNABLE_TO_GET_ISSUER_CERT_LOCALLY - CI/CD 流水线里 Node.js 脚本请求内部服务失败,但手动 curl 成功(curl 默认用系统 CA)
快速验证:用 openssl 看服务器到底发了哪些证书
先确认问题是否真出在服务端证书链不全:
openssl s_client -connect api.dev.example.com:443 -showcerts
观察输出中是否有多个 -----BEGIN CERTIFICATE----- 块。如果没有中间证书(只有服务证书),说明服务端配置漏了 SSLCertificateChainFile 或 Nginx 的 ssl_trusted_certificate,这是运维要修的点,不是你本地加证书能绕过的。
如果链是完整的,那问题就在 Node.js 这边没加载对应根证书。此时可临时绕过验证(仅限调试):
- 加环境变量:
NODE_TLS_REJECT_UNAUTHORIZED=0(⚠️生产禁用) - 或在代码里加
rejectUnauthorized: false(仅限https.request选项)
正确加载私有 CA 证书的三种方式
别改 Node.js 源码或全局替换内置 CA,用以下任一方式注入即可:
-
方式一(推荐):用
NODE_EXTRA_CA_CERTS把公司根证书(.pem 格式)路径设为环境变量,Node.js 启动时自动合并进信任链:NODE_EXTRA_CA_CERTS=/path/to/internal-root-ca.pem node index.js
VSCode 调试时,在launch.json的env字段里加:"env": { "NODE_EXTRA_CA_CERTS": "${workspaceFolder}/certs/internal-root-ca.pem" } -
方式二:在代码里显式传入
ca选项 适用于单个请求,比如用https.request:const ca = fs.readFileSync('./certs/internal-root-ca.pem');https.request({ hostname, port, path, ca })
注意:不能和rejectUnauthorized: false同时用,否则ca被忽略 -
方式三:改 npm 配置(仅影响 npm 自身)
npm config set cafile /path/to/internal-root-ca.pem
这只会让npm install信任该 CA,不影响你的业务代码
容易踩的坑:证书格式、路径、权限
很多问题不是逻辑错,而是文件细节翻车:
-
.pem文件必须是纯文本,以-----BEGIN CERTIFICATE-----开头,不能是.crt或.cer二进制格式(可用openssl x509 -in cert.crt -out cert.pem -outform PEM转) - 路径必须是绝对路径(
NODE_EXTRA_CA_CERTS不支持相对路径),且 VSCode 调试时${workspaceFolder}是项目根目录,不是launch.json所在目录 - 证书文件需对当前用户可读,Linux/macOS 上检查:
ls -l certs/internal-root-ca.pem,避免权限为600且属主不是运行 Node 的用户 - 如果用 WSL2,证书路径要指向 Linux 子系统内的路径(如
/home/user/project/certs/...),不能填 Windows 的C:\...
最隐蔽的一点:某些私有 CA 证书里带了多余空格或 BOM 头,Node.js 读取会静默失败。用 cat -A cert.pem 查看是否有 ^M 或 ^@,有的话用 dos2unix 或 VSCode 保存为 UTF-8 无 BOM 格式。


















