这是情况。我创建了一个自签名CA证书,并使用它来签署第二个证书以用于https。 Web服务器是nginx进行SSL终止并反向代理到expressjs应用程序。为了验证信任链是否正确,我在Firefox中安装了CA,并且能够按预期在没有警告的情况下通过https访问网站。此外,我可以使用request.get({url: theUrl, ca: fs.readFileSync("./ca.crt")}, ...
检查服务器的证书,我会看到预期的发行者,特别是主题的预期通用名称。 (注意:此处使用的通用名称是IP地址,以防可能导致问题。)
但是,当我尝试使用requestjs通过nodejs脚本访问服务器时,事情并不顺利。在脚本中,使用以下代码加载CA证书:
Contacting doorman failed: Error: Hostname/IP doesn't match certificate's altnames:
"IP: <redacted> is not in the cert's list: "
但是我得到了这个错误(为了便于阅读而破了一行,原来是一行):
rejectUnauthorized: false
特别怀疑它似乎是在说“证书清单”是空的。在其他答案中已经在选项中使用了openssl x509 -text
,但对于此应用程序来说,这不是一个很好的选择,因为我想要进行身份验证。
如何让requestjs / nodejs信任此证书?
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 3 (0x3)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=State, L=City, O=Company, CN=www.company.com
Validity
Not Before: Dec 7 17:19:51 2015 GMT
Not After : Oct 14 17:19:51 2025 GMT
Subject: C=US, ST=State, L=City, O=Company, CN=1.2.3.4/emailAddress=webmaster@company.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
...
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
...
[ req ]
default_bits = 4096
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
countryName = "US"
stateOrProvinceName = "State"
localityName = "City"
organizationName = "Company"
commonName = "1.2.3.4"
emailAddress = "webmaster@company.com"
[ v3_req ]
subjectAltName = IP:1.2.3.4
用于生成该证书的配置文件:
SIGABRT
答案 0 :(得分:3)
主机名/ IP与证书的altnames不匹配:
我的猜测是,您的证书包含URL中仅用作主题(CN)的正确主机名,而不是主题备用名称(SAN),但它包含其他名称作为SAN。标准非常明确,如果给出任何主题备用DNS名称,则不应检查CN,但大多数浏览器仍然检查CN(我认为Safari更严格)。但是node.js实现了严格的行为,因此会失败。
如果我的猜测是正确的(没有证书很难看到),那么必须通过创建正确的证书来解决问题。另一种可能性是你在浏览器和nodejs中使用稍微不同的URL(比如有和没有www
前缀)。
编辑:看到你实际使用的证书后....
您在CN中拥有IP地址的证书。虽然大多数浏览器也支持此功能,但这是不对的。 IP地址必须作为ipadress SAN条目而不是CN。 Nodejs只在那里期待它,我认为Safari也是如此严格。请注意,对于IE,您必须将其置于CN或dnsname SAN条目中,因为它们在这种情况下也喜欢与标准相反。因此,为了安全起见,将其作为ipaddress,dnsname,也可能作为CN。