解决Newman接口测试中SSL证书验证失败的四种方案

📅 2026/7/28 22:33:01
解决Newman接口测试中SSL证书验证失败的四种方案
1. 项目概述当Newman遇上SSL证书验证失败如果你在用Postman的Newman做接口自动化测试尤其是在公司内网或者测试环境里十有八九都踩过这个坑SSL certificate verification failed。这行红字报错就像一堵墙把你和你要测试的服务隔开了。我这些年做持续集成Newman是命令行里跑接口测试的主力但每次对接开发刚部署的、还用着自签名证书的服务或者测试环境走代理才能访问时这个SSL验证问题就准时来“报到”。这不仅仅是Postman或Newman的问题而是整个HTTPS安全体系在测试环节的一个典型摩擦点——生产环境要求绝对安全但测试环境又需要灵活和效率。简单来说这个标题描述的场景就是你想用NewmanPostman的命令行工具去测试一个HTTPS接口但这个接口的SSL证书不是由公共信任的证书颁发机构如Let‘s Encrypt, DigiCert签发的而是自己生成的“自签名证书”或者你的网络请求需要经过一个代理服务器比如公司的防火墙代理而Newman在验证证书链时失败了导致请求无法发出。这背后的核心矛盾在于Newman以及其底层的Node.js默认严格遵守SSL/TLS协议的安全规范它会校验服务器的证书是否可信。自签名证书不在其信任的根证书列表里某些代理服务器也可能使用自签名证书进行中间人解密这正是抓包工具的原理因此会被视为不可信从而拒绝连接。这个问题不解决自动化测试流程就卡住了。手动在Postman GUI里点一下“关闭SSL验证”很简单但Newman是跑在CI/CD流水线里的必须通过配置来解决。接下来我就把处理这个问题的完整思路、具体配置和踩过的坑系统地梳理一遍。2. 核心需求与场景解析2.1 为什么会有自签名证书和代理在深入解决方案前得先明白我们为什么会遇到这些“非标准”的证书。自签名证书在开发和测试环境太常见了。理由很简单免费和快速。给内部测试服务器申请一个受公共信任的SSL证书要么花钱要么需要配置域名解析和ACME客户端对于频繁重建的测试环境来说太麻烦了。开发人员自己用OpenSSL或者Keytool生成一个证书几分钟就能让服务跑在HTTPS上。虽然浏览器会报“不安全”但功能测试不受影响。然而像Newman、cURL、Python Requests这类命令行工具默认的安全策略比浏览器更严格它们没有那个“高级”-“继续前往不安全网站”的按钮。代理环境则是企业网络的常态。公司的出口流量通常统一经过一个代理服务器用于安全审计、流量过滤或加速。有些代理服务器为了解密并审查HTTPS流量即SSL Inspection会向客户端动态签发一个证书。这个证书对于你的机器来说也是一个“自签名”证书只不过签发者是公司的内部CA。如果你的系统或Newman没有安装并信任这个内部CA的根证书那么验证自然会失败。2.2 Newman SSL验证失败的深层原理Newman本质上是Node.js应用它发送HTTP请求的能力依赖于Node.js内置的https模块。当它向一个HTTPS URL发起请求时会发生以下几件事TCP连接建立首先与服务器建立TCP连接。TLS握手开始TLS握手协商。服务器会将其证书链发送给客户端Newman。证书验证Node.js的https模块会进行一系列验证证书是否过期检查证书的有效期。证书的域名是否匹配检查证书中的Common Name (CN)或Subject Alternative Names (SAN)是否包含你请求的主机名。证书链是否可信这是最关键的一步。Node.js会检查服务器的证书是否由一个它信任的根证书颁发机构CA签发。它会遍历证书链直到找到一个存在于其“信任存储”Trust Store中的根证书。自签名证书的签发者就是自己它不在信任存储中因此验证失败。代理签发的证书如果其根CA公司的内部CA未安装到信任存储同样失败。验证结果处理如果任何一步验证失败Node.js默认会抛出UNABLE_TO_VERIFY_LEAF_SIGNATURE或CERT_HAS_EXPIRED等错误Newman接收到这个错误后就会终止请求并输出我们看到的失败信息。理解了这个流程我们的解决方案就清晰了要么让Node.js信任这个“不标准”的证书要么在特定请求中跳过这个严格的验证。显然在生产环境或对外部服务的测试中绝不能跳过验证。但对于明确可控的内网测试环境我们可以采取更灵活的策略。3. 解决方案全景与策略选择面对SSL验证失败我们有几种不同粒度的解决策略从“图省事但风险高”到“一劳永逸但稍麻烦”。选择哪种取决于你的具体场景和安全要求。策略一全局禁用SSL验证不推荐但最快这是最粗暴的方法直接让NewmanNode.js忽略所有SSL证书错误。强烈不建议在任何可能接触到生产数据或外部服务的环境中使用。它完全破坏了HTTPS的安全保障让你暴露在中间人攻击的风险下。但在一个完全隔离的、纯内网的开发测试环境中作为临时调试手段可以快速使用。策略二针对Newman运行禁用验证常用折中方案通过向Newman传递一个Node.js环境变量NODE_TLS_REJECT_UNAUTHORIZED0可以仅在此次Newman运行进程中禁用证书验证。这比全局修改Node.js配置要好因为影响范围仅限于当前命令行会话。在CI/CD脚本中这是一种常见的做法前提是你完全信任测试目标环境。策略三信任特定证书最安全推荐这是最规范、最安全的方法。将测试服务器的自签名证书或公司代理的根证书导入到运行Newman所在机器的系统或Node.js的信任存储中。这样Node.js在验证时就能找到可信的根证书验证自然通过。这模拟了浏览器安装私有根证书的行为既保证了安全又解决了连接问题。这是为测试环境建立长期自动化测试的基础。策略四通过Postman GUI预配置并导出Postman GUI客户端提供了方便的开关来管理SSL验证。你可以为某个集合Collection或环境Environment关闭SSL验证。然后当你用Newman运行这个导出的集合时这个设置理论上会被继承。这是一个非常“Postman”风格的解决方案将配置可视化。下面我们分别深入这几种策略的具体操作和细节。4. 实操指南四种解决方案的详细步骤4.1 方案一全局禁用Node.js SSL验证极其不推荐如前所述这是下策。修改Node.js的全局设置会影响该机器上所有Node.js应用。操作方法在Linux/macOS的shell配置文件如~/.bashrc,~/.zshrc或Windows的环境变量中添加一个永久变量。# Linux/macOS echo export NODE_TLS_REJECT_UNAUTHORIZED0 ~/.bashrc source ~/.bashrc # Windows (PowerShell以管理员身份运行) [System.Environment]::SetEnvironmentVariable(NODE_TLS_REJECT_UNAUTHORIZED, 0, [System.EnvironmentVariableTarget]::Machine)重启终端后所有Node.js程序包括Newman都将忽略SSL错误。警告这样做将使你的Node.js运行环境对所有HTTPS中间人攻击毫无防备。仅在绝对隔离、无任何安全风险的实验机器上考虑此方法并且完成后务必移除该变量。4.2 方案二单次运行Newman时禁用验证这是CI/CD脚本中最常见的临时解决方案。通过在运行Newman的命令前设置环境变量其作用域仅限于该次命令。操作方法# Linux/macOS NODE_TLS_REJECT_UNAUTHORIZED0 newman run your_collection.json # Windows (Command Prompt) set NODE_TLS_REJECT_UNAUTHORIZED0 newman run your_collection.json # Windows (PowerShell) $env:NODE_TLS_REJECT_UNAUTHORIZED0; newman run your_collection.json实操心得在Jenkins、GitLab CI等工具中你可以在script步骤直接定义这个环境变量。为了脚本清晰我通常会写一个包装脚本明确标出这里禁用了SSL验证并注明原因例如run_test_insecure.sh。即使这样我也只会在测试指向*.test.internal,*.lab这类明确的内网域名时使用。4.3 方案三安装并信任自签名证书规范做法这是最推荐的长期解决方案。假设你有一个自签名证书文件server.crt。步骤1获取证书文件你需要从服务器导出其证书。如果服务器在你掌控中直接找到生成的.crt或.pem文件。如果没有可以用OpenSSL命令从服务器获取openssl s_client -connect your-test-server.com:443 -showcerts /dev/null 2/dev/null | openssl x509 -outform PEM server.crt将your-test-server.com:443替换为你的服务器地址和端口步骤2将证书添加到系统信任库macOS:sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain server.crtLinux (Ubuntu/Debian):sudo cp server.crt /usr/local/share/ca-certificates/ sudo update-ca-certificatesWindows:双击server.crt文件。点击“安装证书”。选择“本地计算机”点击“下一步”。选择“将所有的证书都放入下列存储”点击“浏览”选择“受信任的根证书颁发机构”点击“确定”后完成。步骤3验证Node.js是否信任Node.js默认使用系统的信任存储。安装后可以创建一个简单的Node.js脚本来测试const https require(https); https.get(https://your-test-server.com, (res) { console.log(成功状态码, res.statusCode); }).on(error, (e) { console.error(失败, e.message); });如果成功那么Newman也一定能成功。针对代理证书如果问题是公司代理的证书你需要从IT部门获取公司内部CA的根证书通常是一个.crt文件然后按照上述同样的步骤将其安装到“受信任的根证书颁发机构”中。这样所有由这个CA签发的证书包括代理为你动态生成的都会被信任。4.4 方案四利用Postman GUI配置并导出Postman允许你为整个集合或特定请求关闭SSL验证。这个设置会保存在集合或环境文件中Newman在运行时可以读取。操作步骤在Postman中打开你的集合。点击集合名称右侧的“...”图标选择“Edit”。在弹出的窗口中切换到“Authorization”或“Pre-request Scripts”标签页不对SSL验证设置在别处。更直接的方法是点击左上角的“眼睛”图标环境管理旁边的“齿轮”图标进入“Settings”。在设置面板中选择“General”选项卡。向下滚动找到“SSL certificate verification”选项将其切换为“OFF”。注意这个设置是全局的会影响所有请求不安全。更好的做法集合级别在集合的“Pre-request Script”中添加一段脚本只对该集合的请求生效pm.request.url.protocol https; // 这个设置可能不会影响底层的Node.js TLS验证更可靠的方法还是前面几种。 // Postman GUI的关闭SSL验证在Newman中不一定完全生效取决于导出格式和Newman版本。实际上更可靠的方法是使用Postman的“代理”配置或直接使用方案二和三。经过我多次测试Postman GUI里关闭SSL验证后导出的集合用Newman运行时有时仍需配合NODE_TLS_REJECT_UNAUTHORIZED0环境变量。因此此方案稳定性欠佳不作为首选。5. 进阶配置Newman与代理服务器的协同在很多企业环境你不仅要处理证书还要让Newman正确使用代理服务器。这又分两种情况普通代理和需要认证的代理。5.1 配置HTTP/HTTPS代理通过环境变量告诉Node.jsNewman所有HTTP/HTTPS流量都走指定的代理。# 设置代理环境变量 export HTTP_PROXYhttp://your-proxy.com:8080 export HTTPS_PROXYhttp://your-proxy.com:8080 # 然后运行Newman此时Newman的请求会通过代理发出 newman run collection.json如果你的代理服务器也使用自签名证书那么即使配置了代理依然会遇到SSL验证失败。此时你需要将代理服务器的根证书而非目标服务器的证书按照方案三安装到信任库中。因为TLS连接首先发生在你的客户端和代理服务器之间。5.2 处理需要认证的代理如果代理服务器需要用户名密码认证在环境变量中直接包含即可export HTTPS_PROXYhttp://username:passwordyour-proxy.com:8080注意将密码明文写在脚本或环境变量中存在安全风险。在CI/CD系统中应使用该平台提供的安全凭证管理功能如Jenkins的Credentials Binding、GitLab的CI/CD Variables masked。5.3 使用newman命令的--insecure选项从Newman v5.0版本开始提供了一个原生选项--insecure来禁用SSL证书验证。这本质上是方案二的另一种便捷形式。newman run your_collection.json --insecure这个选项非常直观推荐在Newman版本支持的情况下使用。6. 常见问题排查与实战技巧即使按照上述步骤操作你可能还是会遇到一些古怪的问题。下面是我总结的排查清单和技巧。6.1 问题速查表现象可能原因排查步骤UNABLE_TO_VERIFY_LEAF_SIGNATURE证书链不完整或根证书不受信。1. 用openssl s_client -showcerts检查服务器返回的证书链是否完整。2. 确保自签名证书或中间CA证书已正确安装到信任库。CERT_HAS_EXPIRED服务器证书已过期。1. 检查证书有效期。2. 如果是自签名证书重新生成一个有效期更长的。HOSTNAME_MISMATCH请求的域名与证书中的域名不匹配。1. 确保证书的CN或SAN字段包含你使用的域名或IP。2. 如果是IP访问证书SAN中必须包含该IP地址IP地址作为DNS名。配置了代理仍无法连接1. 代理地址/端口错误。2. 代理需要认证但未提供。3. 代理本身有SSL证书问题。1. 用curl -x proxy https://example.com测试代理是否通畅。2. 检查代理认证信息。3. 为代理CA证书执行信任操作方案三。NODE_TLS_REJECT_UNAUTHORIZED0无效1. 环境变量未正确生效。2. 某些Node.js库可能不遵循此变量。1. 在脚本中echo $NODE_TLS_REJECT_UNAUTHORIZED确认值是否为0。2. 尝试使用--insecure选项。Newman报告成功但无实际请求可能触发了本地杀毒软件或防火墙的SSL扫描拦截。临时禁用杀毒软件的HTTPS扫描功能或将Newman/node.exe加入白名单。6.2 实战技巧与心得证书链完整性是关键很多时候服务器配置的不是单个证书而是一个证书链服务器证书中间CA证书。你需要确保发送给客户端的链是完整的。用openssl s_client -connect host:443 -showcerts命令查看应该能看到从服务器证书到根证书或接近根证书的完整链条。如果链不完整客户端可能无法构建信任路径。IP地址访问的坑如果你的测试环境直接用IP地址如https://192.168.1.100那么证书的Subject Alternative Name (SAN)里必须包含这个IP地址。很多自签名证书生成工具默认只填域名不填IP导致HOSTNAME_MISMATCH。用OpenSSL生成证书时务必在配置文件中通过subjectAltName IP:192.168.1.100来指定。区分“系统信任库”和“Node.js信任库”绝大多数情况下Node.js使用系统信任库。但在某些通过nvm安装的Node.js版本或特定的Docker镜像中Node.js可能维护自己的一份信任库。如果你已经将证书安装到系统但仍失败可以尝试将证书文件路径直接通过Node.js的NODE_EXTRA_CA_CERTS环境变量指定export NODE_EXTRA_CA_CERTS/path/to/your/self-signed-cert.crt newman run collection.json这个变量允许你指定一个或多个额外的PEM格式CA证书文件Node.js会将这些证书加入其信任列表。Docker中的Newman在Docker容器内运行Newman时容器内的系统信任库通常是干净的不包含你宿主机的证书。你有两个选择一是在构建Docker镜像时将你的CA证书复制到容器的/usr/local/share/ca-certificates/并运行update-ca-certificates二是在运行容器时通过-e NODE_TLS_REJECT_UNAUTHORIZED0传递环境变量仅用于测试。更规范的做法是构建包含必要CA证书的基础镜像。记录与调试当问题复杂时启用Node.js的调试输出能提供巨大帮助NODE_DEBUGtls,https NODE_TLS_REJECT_UNAUTHORIZED0 newman run collection.json这会打印出详细的TLS握手和HTTPS请求信息帮你精准定位是在哪一步失败的。处理Newman的SSL验证问题本质上是在安全规范和测试便利性之间寻找平衡点。对于持续集成的测试环境我个人的最佳实践是推动运维或开发团队为测试域名申请内部私有CA签发的证书并将该私有CA的根证书预装到所有测试机和CI节点的系统信任库中。这样既能保证HTTPS通道的安全防止内网嗅探又能让包括Newman在内的所有自动化工具无缝工作是兼顾安全与效率的长期方案。如果暂时无法实现那么明确边界在CI脚本中使用--insecure标志并辅以清晰的注释也是一种务实的临时选择。记住永远清楚你禁用验证的环境是什么并避免将这种配置泄露到生产流程中。