我尝试使用网址从jira服务器下载文件,但我收到了错误消息。 如何在代码中包含证书以进行验证 的错误:
Error: unable to verify the first certificate in nodejs
at Error (native)
at TLSSocket.<anonymous> (_tls_wrap.js:929:36)
at TLSSocket.emit (events.js:104:17)
at TLSSocket._finishInit (_tls_wrap.js:460:8)
我的Nodejs代码:
var https = require("https");
var fs = require('fs');
var options = {
host: 'jira.example.com',
path: '/secure/attachment/206906/update.xlsx'
};
https.get(options, function (http_res) {
var data = "";
http_res.on("data", function (chunk) {
data += chunk;
});
http_res.on("end", function () {
var file = fs.createWriteStream("file.xlsx");
data.pipe(file);
});
});
答案 0 :(得分:80)
除了盲目接受未经授权的终点之外,这总是比一个更安全的选择,而这应该只是作为最后的手段使用。
这可以像添加
一样简单require('https').globalAgent.options.ca = require('ssl-root-cas/latest').create();
到你的申请。
SSL Root CAs npm package(这里使用的)是关于这个问题的一个非常有用的包。
答案 1 :(得分:54)
unable to verify the first certificate
证书链不完整。
这意味着您要连接的Web服务器配置错误,并且在发送给您的证书链中未包含中间证书。
最有可能如下所示:
中间证书应与服务器证书一起安装在服务器上。
根证书已嵌入到软件应用程序,浏览器和操作系统中。
提供证书的应用程序必须发送完整的链,这意味着服务器证书本身以及所有中间产品。客户端应该知道根证书。
使用浏览器转到https://incomplete-chain.badssl.com。
它没有显示任何错误(地址栏中的挂锁为绿色)。
这是因为浏览器往往不是从服务器发送来的,便会完成该链。
现在,使用节点连接到https://incomplete-chain.badssl.com:
// index.js
const axios = require('axios');
axios.get('https://incomplete-chain.badssl.com')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
日志:“ 错误:无法验证第一个证书”。
您需要自己完成证书链。
要这样做:
1::您需要以.pem
格式获取丢失的中间证书,然后
2a:使用NODE_EXTRA_CA_CERTS
2b:或使用ca
选项传递您自己的证书捆绑包(中间件和根)。
使用openssl
(Git for Windows附带)。
保存远程服务器的证书详细信息:
openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile
我们正在寻找颁发者(中间证书是服务器证书的颁发者/签名者):
openssl x509 -in logcertfile -noout -text | grep -i "issuer"
它应该给您签名证书的URI。下载:
curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt
最后,将其转换为.pem
:
openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text
我正在使用cross-env在package.json
文件中设置环境变量:
"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"
ca
选项此选项将覆盖节点的内置根CA。
这就是为什么我们需要创建自己的根CA。使用ssl-root-cas。
然后,创建一个自定义https
代理,该代理配置了我们的证书捆绑包(根证书和中间证书)。提出请求时,将此代理传递给axios
。
// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();
rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});
axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
您可以将证书放在https
全局代理上,而不用创建自定义的axios
代理并将其传递给https
:
// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;
答案 2 :(得分:32)
无法验证nodejs中的第一个证书是否需要未经授权
request({method: "GET",
"rejectUnauthorized": false,
"url": url,
"headers" : {"Content-Type": "application/json",
function(err,data,body) {
}).pipe(
fs.createWriteStream('file.html'));
答案 3 :(得分:25)
另一个肮脏的黑客攻击,会使你的所有请求都不安全:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
答案 4 :(得分:18)
您尝试下载的服务器配置可能不正确。即使它在您的浏览器中有效,它也可能不包括缓存空客户端验证所需的链中的所有公共证书。
我建议您使用SSLlabs工具检查网站:https://www.ssllabs.com/ssltest/
查找此错误:
此服务器的证书链不完整。
而且:
连锁问题.........不完整
答案 5 :(得分:5)
您可以通过修改请求选项来执行此操作,如下所示。如果您使用自签名证书或缺少中间人,则将strictSSL设置为false将不会强制请求包验证证书。
var options = {
host: 'jira.example.com',
path: '/secure/attachment/206906/update.xlsx',
strictSSL: false
}
答案 6 :(得分:1)
GoDaddy SSL CCertificate
我尝试使用GoDaddy证书连接到我们的后端API服务器时遇到过这种情况,这是我用来解决问题的代码。
var rootCas = require('ssl-root-cas/latest').create();
rootCas
.addFile(path.join(__dirname, '../config/ssl/gd_bundle-g2-g1.crt'))
;
// will work with all https requests will all libraries (i.e. request.js)
require('https').globalAgent.options.ca = rootCas;
<强> PS:强>
使用捆绑的证书,不要忘记安装库npm install ssl-root-cas
答案 7 :(得分:1)
这实际上为我解决了问题,https://www.npmjs.com/package/ssl-root-cas
// INCORRECT (but might still work)
var server https.createServer({
key: fs.readFileSync('privkey.pem', 'ascii')
, cert: fs.readFileSync('cert.pem', 'ascii') // a PEM containing ONLY the SERVER certificate
});
// CORRECT (should always work)
var server https.createServer({
key: fs.readFileSync('privkey.pem', 'ascii')
, cert: fs.readFileSync('fullchain.pem', 'ascii') // a PEM containing the SERVER and ALL INTERMEDIATES
});
答案 8 :(得分:1)
您可以全局禁用证书检查-不管您使用哪个软件包进行请求-
// Disable certificate errors globally
// (ES6 imports (eg typescript))
//
import * as https from 'https'
https.globalAgent.options.rejectUnauthorized = false
或
// Disable certificate errors globally
// (vanilla nodejs)
//
require('https').globalAgent.options.rejectUnauthorized = false
当然您不应该这样做-但对于调试和/或非常基本的脚本而言,它绝对方便,因为您绝对不关心证书是否正确验证。
答案 9 :(得分:0)
我正在使用nodemailer npm模块。下面的代码解决了这个问题
tls: {
// do not fail on invalid certs
rejectUnauthorized: false
}
答案 10 :(得分:0)
这对我有用=>添加代理并将'rejectUnauthorized'设置为false
const https = require('https'); //Add This
const bindingGridData = async () => {
const url = `your URL-Here`;
const request = new Request(url, {
method: 'GET',
headers: new Headers({
Authorization: `Your Token If Any`,
'Content-Type': 'application/json',
}),
//Add The Below
agent: new https.Agent({
rejectUnauthorized: false,
}),
});
return await fetch(request)
.then((response: any) => {
return response.json();
})
.then((response: any) => {
console.log('response is', response);
return response;
})
.catch((err: any) => {
console.log('This is Error', err);
return;
});
};
答案 11 :(得分:0)
解决此问题的另一种方法是使用以下模块。
node_extra_ca_certs_mozilla_bundle
该模块可以通过生成包含Mozilla信任的所有根证书和中间证书的PEM文件而无需进行任何代码修改即可工作。您可以使用以下环境变量(适用于Nodejs v7.3 +),
生成与以上环境变量一起使用的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
注意:我是上述模块的作者。
答案 12 :(得分:0)
几天前我遇到了这个问题,这是我遵循的方法,并且对我有效。
对我来说,这是在我尝试使用axios或在公司防火墙下获取库时发生的,所以我们有某些特定的证书,node js证书存储无法指向。
因此,对于我的loclahost,我采用了这种方法。 我在项目中创建了一个文件夹,并将整个证书链保留在该文件夹中以及我的dev-server( package.json )脚本中,并与服务器脚本一起添加,以便节点js可以引用路径。
"dev-server":set NODE_EXTRA_CA_CERTS=certificates/certs-bundle.crt
对于我的服务器(不同的环境),我如下创建了一个新的环境变量,并添加了它。我使用的是Openshift,但我想这个概念对于其他服务器也将相同。
"name":NODE_EXTRA_CA_CERTS
"value":certificates/certs-bundle.crt
由于我已经可以使用整个证书链,因此我没有生成任何证书。
答案 13 :(得分:0)
我遇到了非常罕见的情况,但希望它可以对某人有所帮助:制作了一个代理服务,将请求代理到另一个服务。即使我添加了所有预期的证书,每个请求的错误都是“无法验证第一个证书”。
原因很简单 - 我不小心重新发送了“主机”标头。 只要确保您没有明确发送“主机”标头即可。
答案 14 :(得分:0)
我能够通过 mozilla 或 chrome 等浏览器获取证书链。
----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
......
-----END CERTIFICATE-----
----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
......
-----END CERTIFICATE-----
import https from 'https'
import cas from 'ssl-root-cas'
......
<块引用> interface CaList extends Buffer {
addFile(file: string): Buffer[]
}
const caList = cas.create() as CaList
caList.addFile(process.env.PROJECT_PATH + 'certs/first-chain.pem')
caList.addFile(process.env.PROJECT_PATH + 'certs/second-chain.pem')
然后当我需要建立 websocket wss 连接时,我将带有新 cas 列表的代理添加到请求中
<块引用>this.client.connect(KtUrl, undefined, undefined, undefined, {
agent: new https.Agent({
ca: caList
})
})
还必须为 ssl-root-cas 文件名添加定义文件 ssl-root-cas.d.ts 以便打字稿不会抱怨
<块引用>declare module 'ssl-root-cas' {
function create(): string | Buffer | (string | Buffer)[] | undefined
}
答案 15 :(得分:0)
在开发环境中设置:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';