无法验证叶子签名


142

我正在使用node.js request.js到达api。我收到这个错误

[错误:UNABLE_TO_VERIFY_LEAF_SIGNATURE]

我所有的凭据都是准确有效的,并且服务器还不错。我对邮递员提出了相同的要求。

request({
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

此代码仅在可执行脚本ex中运行。node ./run_file.js,那是为什么?是否需要在服务器上运行?


这是一个很长的路要走,但是可能是API无法识别您的节点程序正在传递的用户代理吗?
赫克托·科雷亚


@HectorCorrea我能够完美地阅读邮递员中的api。为什么节点不能这样做?我尝试更改用户代理,但不走运。
ThomasReggi

Answers:


157

注意:以下情况很危险,并且将允许在客户端和服务器之间截取和修改API内容。

这也起作用

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';


22
我对此进行了修改,并感谢您的回答,但这确实对您的安全有害。您应该按照以下@ CoolAJ86的答案添加丢失的CA。
mikemaccana 2014年

4
我正在使用名为的NodeJS插件nodemailernodemailer-smtp-transport并且使用了相同的常规命令。您需要将此添加到您的createTransport对象中:tls:{rejectUnauthorized: false}
LukeP 2014年

3
不过,我猜@LukeP对于nodemailer同样不安全。名称中有一个线索:根据定义,如果某项内容未经联合国授权,则通常要拒绝它。您需要找到一种正确授权的方法(通过正确设置CA证书,如其他答案所述)。
布鲁诺

@Bruno我同意,您应该使用证书正确设置它。我只想为演示设置快速测试,因此我发布的代码是快速修复。我应该在我的评论中以此开头。
LukeP 2015年

1
@mikemaccana如果请求位于同一服务器上,并且您是唯一所有者,则不会出现安全问题。
Binar Web

89

这不是应用程序的问题,而是中间CA签名的证书的问题。如果您接受该事实并且仍要继续,请添加以下内容以请求选项:

rejectUnauthorized: false

完整要求:

request({
    "rejectUnauthorized": false,
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

我现在有这个问题在工作。我提交了一张IT票证,告诉他们SSL可能配置错误-他们告诉我我很疯狂。我可以给他们更多信息来解决此问题吗?
blakev

这实际上是不正确的:正如CoolAJ86和hectorcorrea所提到的,证书有效,但是它是由中间CA签名的。
mikemaccana

80

安全的解决方案

您可以将必要的证书添加到链中,而不是关闭安全性。首先从npm 安装ssl-root-cas软件包:

npm install ssl-root-cas

该软件包包含许多中间证书,浏览器信任这些中间证书,而节点不信任。

var sslRootCAs = require('ssl-root-cas/latest')
sslRootCAs.inject()

将添加缺少的证书。请参阅此处以获取更多信息:

https://git.coolaj86.com/coolaj86/ssl-root-cas.js

另外,请参阅下面的下一个答案


2
Http客户端是否不使用Windows可信根证书颁发机构证书存储?
理查德·柯莱特

1
节点使用二进制文件中捆绑的mozilla证书,并且在您提供自己的ca阵列时会覆盖它们。我不知道它的http模块是否也会使用OS链。但是,OS X上的curl似乎仅使用OS链,并且不允许手动指定的证书。
coolaj86

是否必须为每个进程都运行一次,还是可以运行一次并全局更新证书?
Joshua Snider

证书可能存储在两个位置:(1)内置于node.js二进制文件中;(2)操作系统密钥库。如果您的证书过时,则需要在运行代码中包括它。它不会更改节点二进制文件,也不会更改您的操作系统-仅更改项目文件夹。
coolaj86

1
@Sunkas正是错误消息所说的。我不知道如何更简单地解释它。这是一个只读文件,无法编辑。
coolaj86

45

CoolAJ86的解决方案是正确的,并且不会像使用rejectUnauthorized或禁用所有检查一样损害您的安全性。NODE_TLS_REJECT_UNAUTHORIZED。不过,您可能仍需要显式注入其他CA的证书。

我首先尝试了ssl-root-cas模块包含的根CA :

require('ssl-root-cas/latest')
  .inject();

我仍然以UNABLE_TO_VERIFY_LEAF_SIGNATURE错误告终。然后,我发现谁颁发了我要通过COMODO SSL Analyzer连接到的网站的证书,下载了该权限的证书并尝试仅添加该证书:

require('ssl-root-cas/latest')
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

我最终遇到另一个错误:CERT_UNTRUSTED。最后,我注入了附加的根CA,并包含了“我的”(显然是中间人)CA,该CA有效:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

1
我正在使用COMODO高保证安全服务器CA颁发的证书连接到网站。我从他们的下载页面下载了证书。
2014年

2
谢谢!对于我的问题,我需要添加整个证书链来克服此错误。对于其他参考,这篇文章向我展示了如何通过Firefox轻松导出所需的pem文件:superuser.com/a/97203
mfink 2015年

好,谢谢您的帮助。就我而言,最后这是SSL服务器(而不是节点)的错误配置。并非所有中间证书都已安装在服务器上。
Scott Jungwirth

如果你拿到了证书作为.cer运行此openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crt将其转换TA .crt事先
0x1gene

8

对于Create React App(也会发生此错误,并且这个问题是Google排名第一的问题),您可能正在使用HTTPS=true npm startproxy(在中package.json)转到一些HTTPS API,该HTTPS API在开发时本身就是自签名的。

如果是这种情况,请考虑进行以下更改proxy

"proxy": {
  "/api": {
    "target": "https://localhost:5001",
    "secure": false
  }
}

secure 决定WebPack代理是否检查证书链,并禁用以确保未验证API自签名证书,以便获取数据。


4

rejectUnauthorized: falseprocess.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';不做可能很诱人!它将您暴露给中间攻击的人。

其他答案是正确的,因为问题在于您的证书“由中间CA签名”。有一个简单的解决方案,它不需要第三方库,也不需要ssl-root-cas将任何其他CA注入或注入到节点中。

节点中的大多数https客户端支持选项,这些选项使您可以为每个请求指定一个CA,它将解析UNABLE_TO_VERIFY_LEAF_SIGNATURE。这是一个使用节点的内置int https模块的简单示例。

import https from 'https';

const options = {
  host: '<your host>',
  defaultPort: 443,
  path: '<your path>',
  // assuming the bundle file is co-located with this file
  ca: readFileSync(__dirname + '/<your bundle file>.ca-bundle'),
  headers: {
    'content-type': 'application/json',
  }
};
https.get(options, res => {
  // do whatever you need to do
})

但是,如果可以在托管服务器中配置ssl设置,则最佳解决方案是将中间证书添加到托管提供商。这样,客户端请求者无需指定CA,因为它已包含在服务器本身中。我个人使用namecheap + heroku。对我来说,诀窍是使用创建一个.crt文件cat yourcertificate.crt bundle.ca-bundle > server.crt。然后,我打开此文件,并在第一个证书之后添加换行符。您可以在以下位置阅读更多内容

https://www.namecheap.com/support/knowledgebase/article.aspx/10050/33/installing-an-ssl-certificate-on-heroku-ssl


此错误主要来自本地环境,而不是生产环境中,因此,如果您在本地,则可以这样做:process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] ='0';
Vivex

@Vivex-如果要重点在于测试您的SSL证书的工作方式以及它们如何通过传递,那么在本地环境中这样做是不行的……
dwanderson

2

只是将其放在此处以防他人受骗,我的情况就不同了,有点奇怪。我是通过通过超级代理访问的请求获得此消息的-这个问题与证书(正确设置)无关,而这与我随后通过异步模块的瀑布回调传递超级代理结果有关。解决方法:无需传递整个结果,而只需传递result.body瀑布的回调即可。


2

我有同样的问题。我已经遵循@ThomasReggi和@ CoolAJ86解决方案,并且运行良好,但是我对该解决方案不满意。

因为由于认证配置级别而发生“ UNABLE_TO_VERIFY_LEAF_SIGNATURE”问题。

我接受@thirdender解决方案,但接受部分解决方案。根据nginx官方网站,他们明确提到证书应为服务器证书和链接证书的组合。

在此处输入图片说明


1

您也可以通过将strictSSL设置来尝试false,例如:

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}

0

在子域上安装GoDaddy证书后,我的Apache配置出现问题。我本来以为Node不发送服务器名称指示符(SNI)可能是一个问题,但事实并非如此。使用https://www.ssllabs.com/ssltest/分析子域的SSL证书返回了错误链问题:未完成

gd_bundle-g2-g1.crt通过SSLCertificateChainFileApache指令添加GoDaddy提供的文件后,Node能够通过HTTPS连接,错误消失了。


0

您必须在服务器中包括中间证书。这样可以解决[错误:UNABLE_TO_VERIFY_LEAF_SIGNATURE]


0

安全解决此问题的另一种方法是使用以下模块。

node_extra_ca_certs_mozilla_bundle

通过生成包含Mozilla信任的所有根证书和中间证书的PEM文件,该模块可以在不进行任何代码修改的情况下工作。您可以使用以下环境变量(适用于Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

生成要与上述环境变量一起使用的PEM文件。您可以使用以下方法安装模块:

npm install --save node_extra_ca_certs_mozilla_bundle

然后使用环境变量启动节点脚本。

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

使用生成的PEM文件的其他方法可在以下位置找到:

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

注意:我是上述模块的作者。


0

如果由于使用节点postgres / pg模块而进入此线程,那么比设置NODE_TLS_REJECT_UNAUTHORIZED或更好的解决方案rejectUnauthorized,这将导致连接不安全。

而是配置“ ssl”选项以匹配tls.connect的参数:

{
  ca: fs.readFileSync('/path/to/server-ca.pem').toString(),
  cert: fs.readFileSync('/path/to/client-cert.pem').toString(),
  key: fs.readFileSync('/path/to/client-key.pem').toString(),
  servername: 'my-server-name' // e.g. my-project-id/my-sql-instance-id for Google SQL
}

我写了一个模块,以帮助分析从环境变量这些选项,如PGSSLROOTCERTPGSSLCERTPGSSLKEY

https://github.com/programmarchy/pg-ssl


0

以下命令对我有用:

> npm config set strict-ssl false
> npm cache clean --force

问题是您正尝试从存储库中使用错误或不受信任的SSL [安全套接字层]证书安装模块。清理缓存后,此问题将得到解决。稍后可能需要将其设置为true。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.