我在节点 v4.1.2 上使用节点包 RequestJS v2.65.0
我正在尝试从某些网站(例如 GitHub.com)读取 SSL 证书。 这之前适用于节点 0.12。然而,在节点 4.2.1 上,
getPeerCertificate()
返回 null
。
例如:
request({
url: 'https://github.com'
}, function (err, res, body) {
console.log('err:', err)
console.log('peerCertificate:',res.req.connection.getPeerCertificate());
console.log('authorized:',res.req.connection.authorized);
console.log('authorizationError:',res.req.connection.authorizationError);
});
将打印出来
err: null
peerCertificate: null
authorized: true
authorizationError: null
即安全连接已建立,但证书为空。
根据我(基本)的理解,如果连接被授权,应该有一个对等证书。
我尝试过很多 SSL 站点,结果都是一样的。请求中是否有选项、Node 4 的错误,或者我对 SSL/TLS 在节点中如何工作有误解?
我认为你的问题是因为
getPeerCertificate()
只会在连接处于connected
状态时输出任何内容,但是当你收到响应时,可能已经太晚了。
如果您想要
getPeerCertificate
输出,您应该在 TLS 级别独立执行,如下所示:
const socket = require('tls').connect(443, "github.com", () => {
console.log('client connected',
socket.authorized ? 'authorized' : 'unauthorized');
process.stdin.pipe(socket);
process.stdin.resume();
});
重要! :不要将协议放在 URL 中。相反,使用 require('url').parse(yourURL).hostname 作为目标。
更多信息和示例在这里:https://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback
@nembleton 对于发生这种情况的原因是正确的。 https://github.com/request/request/issues/1867
有一个问题您可以坚持使用 Request 并使用其流 API,而不是使用原始 TLS 套接字。如果您正在利用其他使低级连接更加复杂的请求功能(例如通过 HTTPS 代理),则此方法特别有用。
原问题中的代码片段变为:
request({
url: 'https://github.com'
})
.on('error', function(err) {
console.log('err:', err);
})
.on('response', function (res) {
console.log('peerCertificate:',res.socket.getPeerCertificate());
console.log('authorized:',res.socket.authorized);
console.log('authorizationError:',res.socket.authorizationError);
});
(为了简洁/直接,我使用
res.socket
而不是 res.req.connection
,但两者都可以。)
我在构建 api 来检查 SSL 证书过期时遇到了这个问题。
这是适合我的代码。
import https from 'node:https';
const checkSsl = (hostname) => new Promise((resolve, reject) => {
const req = https.request({
hostname,
agent: new https.Agent({ maxCachedSessions: 0 }), // Disable session caching
}, (res) => {
const certificate = res.socket.getPeerCertificate();
resolve(certificate);
});
req.on('error', (e) => {
reject(e);
});
req.end();
});
当会话建立并缓存时,getPeerCertificate()
将返回null
。但非缓存代理将保证详细的结果。