Lab*_*beo 105 jira ssl-certificate node.js
我正在尝试使用url从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)
Run Code Online (Sandbox Code Playgroud)
我的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);
});
});
Run Code Online (Sandbox Code Playgroud)
小智 103
unable to verify the first certificate
证书链不完整。
这意味着您连接的网络服务器配置错误,并且在它发送给您的证书链中没有包含中间证书。
它很可能如下所示:
中间证书应与服务器证书一起安装在服务器上。
根证书嵌入到软件应用程序、浏览器和操作系统中。
服务证书的应用程序必须发送完整的链,这意味着服务器证书本身和所有中间件。客户端应该知道根证书。
使用浏览器访问https://incomplete-chain.badssl.com。
它没有显示任何错误(地址栏中的挂锁是绿色的)。
这是因为如果不是从服务器发送,浏览器往往会完成链。
现在,使用 Node连接到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);
});
Run Code Online (Sandbox Code Playgroud)
日志:“错误:无法验证第一个证书”。
您需要自己完成证书链。
要做到这一点:
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
Run Code Online (Sandbox Code Playgroud)
我们正在寻找颁发者(中间证书是服务器证书的颁发者/签署者):
openssl x509 -in logcertfile -noout -text | grep -i "issuer"
Run Code Online (Sandbox Code Playgroud)
它应该为您提供签名证书的 URI。下载它:
curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt
Run Code Online (Sandbox Code Playgroud)
最后,将其转换为.pem
:
openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text
Run Code Online (Sandbox Code Playgroud)
我正在使用cross-env在package.json
文件中设置环境变量:
"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"
Run Code Online (Sandbox Code Playgroud)
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);
});
Run Code Online (Sandbox Code Playgroud)
您可以将证书放在全局代理上,而不是创建自定义https
代理并将其传递给:axios
https
// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;
Run Code Online (Sandbox Code Playgroud)
Jos*_*hua 99
这总是比盲目接受未经授权的终点更安全的选择,而这些终点反过来只能作为最后的手段使用.
这可以像添加一样简单
require('https').globalAgent.options.ca = require('ssl-root-cas/latest').create();
Run Code Online (Sandbox Code Playgroud)
到您的申请.
该SSL根CA NPM包(这里使用的)是关于这个问题的一个非常有用的包.
小智 41
另一个肮脏的黑客,这将使你的所有请求不安全:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
Run Code Online (Sandbox Code Playgroud)
Lab*_*beo 33
如果无法验证nodejs中的第一个证书,则需要拒绝未经授权
request({method: "GET",
"rejectUnauthorized": false,
"url": url,
"headers" : {"Content-Type": "application/json",
function(err,data,body) {
}).pipe(
fs.createWriteStream('file.html'));
Run Code Online (Sandbox Code Playgroud)
Pin*_*Woo 15
在开发环境中设置:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
Run Code Online (Sandbox Code Playgroud)
或者,先设置环境变量
export NODE_TLS_REJECT_UNAUTHORIZED=0
Run Code Online (Sandbox Code Playgroud)
然后启动应用程序:
node index.js
Run Code Online (Sandbox Code Playgroud)
不适合产品服务。
解决此问题的另一种方法是使用以下模块。
node_extra_ca_certs_mozilla_bundle
该模块可以通过生成包含 Mozilla 信任的所有根证书和中间证书的 PEM 文件来运行,无需任何代码修改。您可以使用以下环境变量(适用于 Nodejs v7.3+),
生成与上述环境变量一起使用的 PEM 文件。您可以使用以下方式安装该模块:
npm install --save node_extra_ca_certs_mozilla_bundle
Run Code Online (Sandbox Code Playgroud)
然后使用环境变量启动节点脚本。
NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js
Run Code Online (Sandbox Code Playgroud)
使用生成的 PEM 文件的其他方法可在以下位置找到:
https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle
注意:我是上述模块的作者。
这实际上为我解决了这个问题,来自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
});
Run Code Online (Sandbox Code Playgroud)
小智 6
您可以通过修改请求选项来执行此操作,如下所示.如果您使用自签名证书或缺少中介,则将strictSSL设置为false将不会强制请求程序包验证证书.
var options = {
host: 'jira.example.com',
path: '/secure/attachment/206906/update.xlsx',
strictSSL: false
}
Run Code Online (Sandbox Code Playgroud)