我在尝试从
unable to verify the first certificate
获取响应时遇到问题 https://testcall.zerophone.us/janus/info
。
我尝试使用
get-ssl-certificate
包获取SSL证书,然后使用fs将pemEncoded写入cert.pem
,并将其添加到httpsAgent。下面是我在初始化 Express 之前获取证书的代码:
let httpsAgent
const handleServerCert = () => {
return new Promise((resolve, reject) => {
sslCertificate.get('testcall.zerophone.us').then(function (certificate) {
console.log('certificate', certificate)
fs.writeFile('cert1.pem', certificate.pemEncoded, async (err) => {
if (err) {
console.error('create cert failed: ' + err);
reject()
} else {
console.log('created cert success!\n')
// https://stackoverflow.com/a/60020493/1308590
const certFile = path.resolve(__dirname, 'cert1.pem')
rootCas.addFile(certFile);
httpsAgent = new https.Agent({ ca: rootCas });
https.globalAgent.options.ca = rootCas;
resolve()
}
});
}).catch(error => {
console.log(`can not get server cert:${SERVER_URL} \nerror: ${error}`)
reject()
});
})
}
const getAgent = () => {
return httpsAgent
}
module.exports = {
handleServerCert,
getAgent
}
在initExpress之后,我使用全局方法将httpsAgents添加到请求中:
static defaultHeader() {
return {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
agent: getAgent()
}
}
但是我仍然遇到错误
unable to verify the first certificate
,我不知道为什么我仍然遇到这个问题,但是如果我从chorme打开网站,然后导出证书,使用这个,一切正常。有人可以帮助我了解我的问题吗?
正如您引用的答案正确所说,您需要将中间 CA 证书(又名链 [CA] 证书) 添加到您的本地信任库。
get-ssl-certificate
没有获得中级CA证书,或任何CA证书;它只获得且始终是 server 又名叶证书。这对于形成信任链没有任何帮助。
像 Chrome 这样的 OTOH 浏览器,正如答案正确所说,通常可以获取丢失的证书(主要是在这里使用 AIA)。如果您从浏览器导出intermediate(不是叶)证书并将其添加到代码中,那就可以了。使用 OpenSSL 和curl 的答案中显示的方法也是如此。或者如果您想要代码:
// I'm not a promiser so that's left as an exercize, plus whatever errorhandling you want
const tls = require('tls'), http = require('http'), fs = require('fs');
function pemEncode(b,l){ return "-----BEGIN "+l+"-----\n"
+ b.toString('base64').replace(/.{64}/g,'$&\n')
+ "\n-----END "+l+"-----\n";
}
function getCert(u){ http.get(u, (res)=>{ var d=[];
res.on('data',(chunk)=>{ d.push(chunk) });
res.on('end',()=>{ fs.writeFileSync('cert1.pem',pemEncode(Buffer.concat(d),'CERTIFICATE')) });
});
}
var host = 'testcall.zerophone.us', port = 443;
// many servers today require SNI to get their cert (or anything else),
// in which case add servername:host, but this one doesn't
const s = tls.connect( {host,port,rejectUnauthorized:false}, ()=>{
getCert( s.getPeerCertificate().infoAccess['CA Issuers - URI'][0]);
s.destroy() });