【问题标题】:Nodejs https request UNABLE_TO_GET_ISSUER_CERT_LOCALLYNodejs https 请求 UNABLE_TO_GET_ISSUER_CERT_LOCALLY
【发布时间】:2015-06-04 18:26:43
【问题描述】:

操作系统:debian sid

Nodejs:v0.10.38

我有一个使用身份验证的私人服务的请求:

var https = require('https');

var options = {
    host: 'private.service.com',
    path: '/accounts/' + '123323' + '/orders',
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': 0,
        'Authorization': 'Bearer ' + 'asdsdgcvxcvxcv'
    }
};

var request = https.request(options, function (res) {
    console.log(res);
});

当我运行脚本时,节点抛出此错误:

events.js:72
    throw er; // Unhandled 'error' event
          ^
Error: UNABLE_TO_GET_ISSUER_CERT_LOCALLY
    at SecurePair.<anonymous> (tls.js:1381:32)
    at SecurePair.emit (events.js:92:17)
    at SecurePair.maybeInitFinished (tls.js:980:10)
    at CleartextStream.read [as _read] (tls.js:472:13)
    at CleartextStream.Readable.read (_stream_readable.js:341:10)
    at EncryptedStream.write [as _write] (tls.js:369:25)
    at doWrite (_stream_writable.js:226:10)
    at writeOrBuffer (_stream_writable.js:216:5)
    at EncryptedStream.Writable.write (_stream_writable.js:183:11)
    at write (_stream_readable.js:602:24)

同样的脚本运行了几个月,我确信身份验证是正确的。今天第一次遇到这种情况。

导致此错误的原因可能是什么?

【问题讨论】:

    标签: node.js ssl https


    【解决方案1】:

    经过一些研究,我发现这是我尝试向其发出 https 请求的服务器的问题。

    节点 https 在 private.service 服务器上找不到 ssl ISSUER_CERT,因此抛出异常。

    我使用的解决方案是添加

                rejectUnauthorized: false
    

    对于https请求的选项,这样节点在证书问题的情况下不会抛出异常。

    无论如何,此解决方案仅在您知道可以信任请求的主机时才有效,否则它可能不是最佳解决方案。

    【讨论】:

    • 查看我的回答,为什么虽然这足以“让它工作”,但它会使您的客户端应用程序受到中间人攻击。
    • 感谢拒绝未授权:假。有效。尽管 zakjan 在他的回答中提到了它,但您已经提到了必须在哪里添加它。
    • 不要这样做。您正在使用 SSL 来确保安全性,然后明确将其关闭,那么为什么要首先使用 SSL 呢?由于您的客户端无法确定服务器的身份,因此您正在向中间人攻​​击开放自己。
    • 在测试或非生产环境中禁用它可能没问题。
    【解决方案2】:

    SSL 是有原因的。除了其他功能外,它还可以验证您是否确实在与private.service.com 主机名标识的服务器进行通信。否则,您的客户端软件可能会被中间人攻击所欺骗。

    首先,当有人遇到此问题时,他们应该更新系统根 SSL 证书。在 Debian 中,它们包含在 ca-certificatesapt-get 包中。

    如果没有帮助,服务器可能使用颁发者证书,默认情况下全球 PKI 基础架构不信任该证书。在这种情况下,客户端应将证书公钥签名与预共享值进行比较。这称为“证书固定”。

    特别是针对您的错误,如果它以前有效,则服务器证书可能已过期。服务器应该更新它。作为临时解决方案,您可以通过 rejectUnauthorized 选项关闭 PKI 验证。但是,您应该将它与固定方法一起使用。在 NodeJS 中,您可以从res.socket.getPeerCertificate().fingerprint 获取服务器证书指纹。

    【讨论】:

    • 我会试试你的建议,我会告诉你的,谢谢你更深入的解释。
    【解决方案3】:

    经过研究,问题解决了:

    npm set strict-ssl=false
    

    希望对你有帮助。

    【讨论】:

    • 是的,它适用于我,但要使用此命令进行更改,您必须在超级用户会话中运行它 -->sudo npm set strict-ssl=false 非常感谢,亲爱的
    • 不要这样做。您正在使用 SSL 来确保安全性,然后明确将其关闭,那么为什么要首先使用 SSL 呢?由于您的客户端无法确定服务器的身份,因此您正在向中间人攻​​击开放自己。
    【解决方案4】:

    来自this GitHub issue,使用以下环境变量:

    export NODE_EXTRA_CA_CERTS=/path/to/certfile.crt
    

    之后,您可以运行任何npm 命令,nodejs 将信任您的额外证书文件。

    .crt 文件是一个包含前缀行、base64 编码证书和后缀行的文件。

    如果您手边没有根 CA 证书,可以使用 openssl 命令从您的 URL 生成证书文件:

    openssl s_client \
        -showcerts \
        -servername <host> \
        -connect <host>:443 2>/dev/null </dev/null | \
      openssl x509
    

    &lt;host&gt; 是 url 的主机名。例如,使用google.com 作为主机,输出如下所示:

    -----BEGIN CERTIFICATE-----
    MIIIIDCCBwigAwIBAgIQI/1aCHwDN94QFUhXJeIwODANBgkqhkiG9w0BAQsFADBU
    (42 more lines)
    E+Hv1bJSbOMSNCDzqRM3JUzvM6Y=
    -----END CERTIFICATE-----
    

    将其保存为您的.crt 文件并将其路径添加到NODE_EXTRA_CA_CERTS 环境变量中,一切就绪。

    【讨论】:

      【解决方案5】:

      当我尝试在 Ubuntu 16 上安装 npm 时,我遇到了同样的错误。 以下命令对我有用。

      npm config set registry http://registry.npmjs.org/
      

      【讨论】:

      • 这很糟糕,因为它不使用 SSL。类似于这样做:npm set strict-ssl=false。除非您根本不关心安全性,否则不要这样做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 2019-05-28
      • 2017-08-02
      • 1970-01-01
      相关资源
      最近更新 更多