节点js - 证书链中的自签名证书错误

141

我在客户端发起HTTPS请求时遇到了问题。

代码片段可能如下所示:

var fs = require('fs');
var https = require('https');

var options = {
    hostname: 'someHostName.com',
    port: 443,
    path: '/path',
    method: 'GET',
    key: fs.readFileSync('key.key'),
    cert: fs.readFileSync('certificate.crt')
}

var requestGet = https.request(options, function(res){
    console.log('resObj', res);
}

我遇到的问题是:错误: 证书链中有自签名证书。

当我使用Postman时,我可以导入客户端证书和密钥,并且可以无任何问题地使用它。是否有任何解决方案可用??我还想了解一下Postman如何处理证书并运作的一些相关信息。

10个回答

227

选项1:禁用警告(适用于开发)

根据您的问题,我猜测您正在开发中使用自签名证书进行SSL通信。

如果是这种情况,请在运行Node的任何地方添加环境变量。

export NODE_TLS_REJECT_UNAUTHORIZED='0'
node app.js

或者直接运行Node

NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js

这会指示Node允许使用不受信任的证书(不受信任意味着未经证书颁发机构验证)

如果您不想设置环境变量或需要为多个应用程序执行此操作,则npm有一个名为strict-ssl的配置项,您可以将其设置为false

npm config set strict-ssl=false

选项 2:像 Postman 一样加载 CA 证书(用于使用 TLS 进行测试)

如果您已经有一个 CA 证书,就像 @kDoyle 提到的那样,那么您可以在每个请求中进行配置(感谢 @nic ferrier)。

 let opts = {
    method: 'GET',
    hostname: "localhost",
    port: listener.address().port,
    path: '/',
    ca: fs.readFileSync("cacert.pem")
  };

  https.request(opts, (response) => { }).end();

选项三:使用来自可信源的适当SSL证书(适用于生产环境)

letsencrypt.org是免费的,易于设置,并且密钥可以自动旋转。https://letsencrypt.org/docs/


如果我理解正确的话,在服务器上设置该“env_var”只会禁用验证过程,而这不是我想要的。我只需要像Postman一样导入证书。 - kDoyle
还有两件事情需要考虑,一是CN必须与您尝试使用的域名相同,二是您的openssl软件包需要是1.0.2+,或者您可以使用免费的CA https://letsencrypt.org/。 - Peter Grainger
看起来我误解了拒绝。它应该在客户端完成,一切都像魅力一样工作。谢谢你,我接受这个答案。 - kDoyle
3
我简直不敢相信我终于找到了能够解决这个错误的方法。我他妈的尝试了所有可能的方法。在2019年1月31日成功运行。 - Anthony Roberts
2
THAAAAAAANKKKSSSSS - WISERDIVISOR
显示剩余8条评论

51

您可以在终端中使用NODE_TLS_REJECT_UNAUTHORIZED=0来解决此问题或将以下行插入JS文件中。

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;

请注意这是一种黑客方法,不应在生产环境中使用。

如果您正在使用Windows,则在命令提示符中运行以下命令:

set NODE_TLS_REJECT_UNAUTHORIZED=0 

之后,npm install <my-package> 就会起作用。


5
应该是 process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; - TheRealFakeNews
2
这个(数字)可以运行,但字符串版本不行。我在Windows上运行node.js。 - Wadi Diaz-wong
两个都可以,第一个(数字)对我有效。 (CentOS) - Kishore
我在Windows上使用自签名证书并使用ftp npm模块时遇到了错误。解决方案是否不同? - Salim Shamim
在MAC上等效的命令是什么? - SymboCoder

18

你可以输入命令 npm config set strict-ssl false


18

Nodemailer相关:

添加

tls: {
  rejectUnauthorized: false
}

问题已解决。

总体代码如下:

nodemailer.createTransport({
    host: process.env.MAIL_SERVER,
    secure: false,
    port: 587,
    auth: {
      user: process.env.MAIL_USERNAME,
      pass: process.env.MAIL_PASSWORD
    },
    tls: {
      rejectUnauthorized: false
    }
  }

1
这正是我正在寻找的。谢谢。 - imvanzen

12

你只需要在你的代码开头添加这行:

process.env.NODE_TLS_REJECT_UNAUTHORIZED='0'

问题已经解决,但是不建议这样做,我正在调查 https://letsencrypt.org/ 的解决方案


3
它能够工作,但我认为这只是一个临时解决方案,只是为了让我们的应用程序运行起来。它会给出以下警告:警告:将NODE_TLS_REJECT_UNAUTHORIZED环境变量设置为“0”会通过禁用证书验证使TLS连接和HTTPS请求不安全。 - Badri Paudel

11

关闭验证是非常危险的事情。最好验证证书。

您可以使用选项对象的ca关键字将证书颁发机构证书导入请求中,如下所示:

let opts = {
    method: 'GET',
    hostname: "localhost",
    port: listener.address().port,
    path: '/',
    ca: await fs.promises.readFile("cacert.pem")
  };

https.request(opts, (response) => { }).end();

我整理了一个完整的演示,以便您可以看到如何构建SSL测试。

这里是链接


6

建议:

如果运行独立的节点脚本,请使用此选项。

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;

不要这么做:

不要改变所有默认请求的处理方式。

npm config set strict-ssl=false

即不要修改节点配置,否则它将应用于所有请求,使其成为默认配置。因此,请仅在必要时使用它。

6

Node应用需要将CA证书添加到现有的CA(Mozilla)证书中。

我们使用服务启动节点,并添加环境变量NODE_EXTRA_CA_CERTS。

[Service]
Restart=always
User=<...>
Group=<...>
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
Environment=NODE_EXTRA_CA_CERTS=/<...>/.ssl/extra_certs.pem
WorkingDirectory=/<...>

ExecStart=/usr/bin/node -r dotenv/config /<.....>/server.js dotenv_config_path=/<....>/.env

这样我们就可以使用同一应用程序来调用使用流行CA或我们自己的自签名证书的服务,而且我们不必关闭SSL检查。

在Linux中有一个简单的方法来获取证书,可以使用这个帖子:使用cURL使用自签名证书?

您可以使用以下命令创建证书:

$ echo quit | openssl s_client -showcerts -servername server -connect server:443 > cacert.pem

然后将该.pem文件复制为 extra_cert.pem。您只能有一个pem文件,但是您可以将多个pem文件追加到一个文件中。

我希望这会对某些人有所帮助,花费了我一段时间来找出组成它的不同部分。


2
这是最佳选择,且不会妥协安全性! - st.huber
使用dotenv这种方法行不通:https://github.com/nodejs/node/issues/20432 - undefined

3

说实话,我花了一天半时间试图追踪这个问题。最终发现错误是由我公司防火墙上的一个设置引起的,需要IT部门禁用它。互联网上没有任何东西可以解决这个问题。


你们的IT部门不得不禁用什么东西? - RushPL

0

编程相关内容:process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; 尽管它没有起作用...

无法安装Cypress:

S C:\Cypress> export NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js export: 术语“export”不被识别为cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。 在行:1字符:1

  • export NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js
  •   + CategoryInfo          : 对象未找到: (export:String) [], CommandNotFoundException   
      + FullyQualifiedErrorId : CommandNotFoundException
    
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接