unable_to_verify_leaf_signature 是 node.js 默认严格校验证书链失败所致,需区分环境:开发时可用 https.agent 配置 ca 或 checkserveridentity 绕过;生产环境必须补全证书链并确保证书 san 包含请求域名。

Node.js 请求报 UNABLE_TO_VERIFY_LEAF_SIGNATURE 怎么办
这是 Node.js 默认校验服务端证书失败的典型表现,不是代码写错了,而是 TLS 握手时找不到可信的 CA 链来验证 PHP、本地 HTTPS 服务或自签名后端返回的证书。常见于用 XAMPP/WAMP 启的本地 HTTPS、内网 API 或测试环境。
- 先确认是不是开发环境:如果是本地
https://localhost:8000或内网域名,大概率是自签名证书,关验证可快速绕过 - 别用
NODE_TLS_REJECT_UNAUTHORIZED=0全局环境变量——它会让整个进程跳过所有 TLS 验证,CI/CD 或上线后极易被删掉导致崩溃 - 真正安全的做法是把 PHP 服务导出的
ca.crt或fullchain.pem文件读进来,作为ca选项传给https.Agent
示例(axios 场景):
const fs = require('fs');
const https = require('https');
const axios = require('axios');
const agent = new https.Agent({
ca: fs.readFileSync('./php-ca.crt') // 路径必须存在且可读
});
axios.get('https://php-api.local/api.php', { httpsAgent: agent })
.then(res => console.log(res.data));
VSCode 调试时 SSL 报错但终端里正常?检查 launch.json 和 PATH
VSCode 启动 Node.js 进程时不会加载 shell 的 .zshrc 或 .bash_profile,所以即使你在终端里能跑通,调试器可能用的是系统自带旧版 Node 或缺失证书路径。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 在 VSCode 内置终端执行
which node和node -v,记下路径;再看launch.json里有没有显式指定runtimeExecutable - 如果没指定,VSCode 会按自己的 PATH 查找,很可能找到的是
/usr/bin/node(macOS 系统自带,无 OpenSSL 支持)而非/opt/homebrew/bin/node - 在
launch.json中强制指定路径:"runtimeExecutable": "/opt/homebrew/bin/node"(macOS Homebrew)或"runtimeExecutable": "C:\Program Files\nodejs\node.exe"(Windows)
用了代理(Clash/Charles)后 VSCode 的 Node.js 请求全挂了
代理工具注入自签名 CA,但 VSCode 启动时没继承终端的 SSL_CERT_FILE 或 REQUESTS_CA_BUNDLE 环境变量,导致 Node.js 无法识别代理证书。
- 临时方案:在
launch.json的env字段里补上证书路径,例如:"SSL_CERT_FILE": "/Users/xxx/.mitmproxy/mitmproxy-ca-cert.pem" - 更稳妥的做法是把代理的根证书导出为 PEM 格式,然后像上一条那样通过
ca选项注入到https.Agent中 - 不要设
"http.proxyStrictSSL": false—— 这个只影响 VSCode 自身的 HTTP 请求(比如扩展更新),对你的 Node.js 调试进程完全无效
为什么加了 ca 选项还是报 ERR_TLS_CERT_ALTNAME_INVALID
这是 Node.js 19+ 版本新增的严格校验:除了证书链,还强制验证证书里的 subjectAltName(SAN)是否匹配请求域名。如果你用的是 localhost 或 IP 地址,而证书里只写了 php-api.local,就会触发这个错误。
- 开发阶段最直接的解法是在
https.Agent里加checkServerIdentity: () => undefined - 但注意:这会跳过主机名比对,仅建议用于明确控制范围的本地调试,不能带进生产代码
- 长期应重签证书,确保 SAN 包含所有测试域名和
localhost,例如:subjectAltName = DNS:php-api.local, DNS:localhost, IP:127.0.0.1
UNABLE_TO_VERIFY_LEAF_SIGNATURE 还是 ERR_TLS_CERT_ALTNAME_INVALID,再决定该补 ca 还是加 checkServerIdentity。










