无论证书有效性如何,我的 node.js https 客户端始终有效

Posted

技术标签:

【中文标题】无论证书有效性如何,我的 node.js https 客户端始终有效【英文标题】:My node.js https client always works regardless of certificate validity 【发布时间】:2012-04-13 14:10:43 【问题描述】:

这个测试程序连接到一个 https 服务器并获取一些内容。我已经在浏览器和 curl 中检查了我的服务器,并且证书工作正常。如果我运行 curl 从服务器获取数据,它会正确地抱怨证书未知,除非我使用 --cacert 传递它或使用 -k 关闭安全性。

所以我遇到的问题是,虽然我认为我的客户应该进行证书身份验证并且我告诉它公共证书在哪里,但它总是有效。如果我删除 ca: 选项,因此它不知道来自服务器的证书是什么,那么它会静默工作。我想捕捉身份验证错误,但我似乎做不到。

var https = require('https');
var fs = require('fs');

function main() 

      var data = '';

      var get = https.get(
        path: '/',
        host: 'localhost',
        port: 8000,
        agent: false,
        ca: [ fs.readFileSync('https_simple/cacert.pem') ]

      , function(x) 

        x.setEncoding('utf8');
        x.on('data', function(c) data += c);
        x.on('error', function(e) 
          throw e;
        );
        x.on('end', function() 
          console.log('Hai!. Here is the response:');
          console.log(data);
        );

      );

      get.on('error', function(e) throw e);

      get.end();

    

main();

【问题讨论】:

【参考方案1】:

为了完成这项工作,我需要升级到 v0.7.8(尽管任何 v0.7 都应该没问题),其中将 rejectUnauthorized 功能添加到 https.get

需要这种选项组合:

agent: false, // or you can supply your own agent, but if you don't you must set to false
rejectUnauthorized: true, 
ca: [ fs.readFileSync('https_simple/cacert.pem') ]

现在,如果身份验证失败,您将收到一个“错误”事件,请求将不会继续。

有关制作自己的代理的详细信息,请参阅 https.request documentation

在此更改中提交了错误修复:https://github.com/joyent/node/commit/f8c335d0

【讨论】:

rejectUnauthorized 是在 0.7.0 版本中添加的 查看文档:nodejs.org/api/tls.html,没有迹象表明 rejectUnauthorized 是为客户端添加的...对于服务器是但不是客户端...您能在此处设置我正确的路径吗?我在这里查看过时的文档吗? 更改列表在上面的答案中。该问题已在github.com/joyent/node/issues/2247 此处进行了跟踪,但我没有查看文档是否已更新,抱歉。【参考方案2】:

根据https.request 的documentation,https.gethttps.requestca 选项是tls.connect 的一个选项。 tls.connect 模块功能的选项文档说明:

ca:受信任证书的字符串或缓冲区数组。如果这是 省略了几个众所周知的“根”CA,例如 VeriSign。 这些用于授权连接。

挖掘 node.js 源代码,使用的根证书可以在这里找到:https://github.com/joyent/node/blob/master/src/node_root_certs.h

因此,简而言之,如果没有为https.get 提供任何授权证书,tls 模块将尝试使用根证书列表对连接进行身份验证。

【讨论】:

这是很好的信息,谢谢。它在这里对我没有帮助,因为我使用的是我自己的自签名证书。我希望连接只有在我传递我的证书时才能工作,但无论哪种方式都可以。 @Перо 有什么方法可以组合服务器证书而不丢失根 CA?例如:ca: [ fs.readFileSync('myServerCert.pem'), node_root_certs.h] 访问头文件中的常量的语法是什么?【参考方案3】:

我在 npm 中使用 request 模块执行此操作。它是这样的:

var cacert = ... // in npm, this is a config setting
var request = require("request")
request.get( url: "https://...",
              ca: cacert,
              strictSSL: true )
  .on("response", function (resp)  ... )
  .on("error", function (er)  ... )

如果 ssl 无效,将引发错误事件。

【讨论】:

【参考方案4】:

在 V 0.6.15 中,无论证书验证通过还是失败,您都需要explicitly check。

if (x.connection.authorized === false)     
   console.log('SSL Authentication failed');
 else if (x.connection.authorized === true)     
   console.log('SSL Authentication succeeded');
 

【讨论】:

这看起来很有希望,但 x.authorized 是未定义的 想必这是要放在回调函数中的。不幸的是,这不会阻止在证书不受信任时发出请求,它只会在完成后告诉您(例如,您可能已经泄露了身份验证凭据)。 @Bruno,这只是版本 0.6 的限制,预计版本 @ZzZombo if-else 不是多余的。最好为第二个if 提供else 子句,但我不知道OP 在这种情况下会做什么。你可能想复习the difference between == and ===

以上是关于无论证书有效性如何,我的 node.js https 客户端始终有效的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Node.js http get 请求中获取数据

如何在 Node JS 上将 http 重定向到 https

无论如何,我可以在 node.js 中获取 html 正文

如何让 Node.Js 允许我为客户端证书提供智能卡/cac

OpenJS基金会推出Node.js证书,JS开发者可以“考证”了

使用 node.js 验证带有 CA 证书的 X509 证书