使用 Boost.Asio 和 OpenSSL 的 HTTPS 请求

Posted

技术标签:

【中文标题】使用 Boost.Asio 和 OpenSSL 的 HTTPS 请求【英文标题】:HTTPS request with Boost.Asio and OpenSSL 【发布时间】:2011-10-26 03:48:15 【问题描述】:

我正在尝试从我的 C++ 应用程序中读取 https://mtgox.com/api/0/data/ticker.php 的股票代码。 我使用 Boost.Asio 和 OpenSSL,因为该服务需要 HTTPS。

加速版本:1.47.0

OpenSSL:1.0.0d [2011 年 2 月 8 日] Win32

对于应用程序;我以http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/ssl/client.cpp 为例 开始并修改如下:

这是我要连接的地方:

boost::asio::ip::tcp::resolver::query query("mtgox.com", "443");

我将验证设置为无,否则握手会失败。我不确定这是否是 mtgox 的问题,或者这个实现是否真的很严格,因为当我将证书打印到屏幕上时,它看起来是合法的(访问代码页面时 chrome 没有问题)。

socket_.set_verify_mode(boost::asio::ssl::context::verify_none);

这是我发送的请求:

std::stringstream request_;

request_ << "GET /api/0/data/ticker.php HTTP/1.1\r\n";
request_ << "Host: mtgox.com\r\n";
request_ << "Accept-Encoding: *\r\n";
request_ << "\r\n";

boost::asio::async_write(socket_, boost::asio::buffer(request_.str()), boost::bind(&client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

(完整代码:http://pastebin.com/zRTTqZVe)

我遇到以下错误:

Connection OK!
Verifying:
/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
Sending request: 
GET /api/0/data/ticker.php HTTP 1.1
Host: mtgox.com
Accept-Encoding: *

Sending request OK!

Read failed: An existing connection was forcibly closed by the remote host

我是否朝着正确的方向前进?错误消息并没有真正描述问题,我不知道我做错了哪一步。

更新: 我用 cURL 看看出了什么问题:

curl --trace-ascii out.txt https://mtgox.com/api/0/data/ticker.php

(完整输出:http://pastebin.com/Rzp0RnAK) 在验证过程中失败。 当我连接“不安全”参数时

curl --trace-ascii out.txt -k https://mtgox.com/api/0/data/ticker.php

(完整输出:http://pastebin.com/JR43A7ux)

一切正常。

修复:

    我修正了 HTTP 标头中的错字 我添加了根证书并 重新开启 SSL 验证。

【问题讨论】:

为什么要生成密钥?你没有签署任何东西,服务器是。不过,您需要信任服务器的根证书。 您是否尝试过发送该请求,例如通过 curl 来查看服务器是否接受它? 好主意!我已经更新了问题。 【参考方案1】:

简而言之:

    您发送的是“HTTP 1.1”而不是“HTTP/1.1”。这肯定足以让服务器拒绝您的请求。您的请求和 cURL 之间还有其他差异,您可能还需要更改这些参数 - 即使它们对我来说似乎有效。

    可能 OpenSSL 没有服务器使用的根证书,这与 Chrome 不同,这就是验证失败的原因。

详情:

    给定一个工作和不工作的工具,你应该总是比较正在发生的事情。在这里,您有 cURL 的输出和您的请求 - 比较它们显示出许多差异;通常,即使使用加密连接,您也可以使用功能强大的数据包嗅探器,例如 Wireshark,它可以从数据包中解码尽可能多的信息。在这里可以看到服务器实际上发送的数据包更少(我期望);另一种可能性是您的客户端没有收到服务器发送的数据(比如说因为客户端有一些错误)。

    如果我理解正确,curl 只显示了您需要禁用验证的原因,对吗?该证书在 chrome 上看起来对我也有效,但根证书颁发机构完全未知; curl 提到了“CA cert”,即证书颁发机构的证书。根证书是受信任的,因为它已经存在于客户端的证书数据库中 - 我认为 Chrome 可能拥有比 OpenSSL 更完整的数据库(cURL 和您的程序都使用它)。

【讨论】:

谢谢!我修正了错字并添加了一个最近的根证书作为 ssl“上下文”,现在一切正常:)。

以上是关于使用 Boost.Asio 和 OpenSSL 的 HTTPS 请求的主要内容,如果未能解决你的问题,请参考以下文章

Boost SSL 编译失败

boost asio - 来自一个线程的 SSL async_read 和 async_write

使用 boost::asio::async_wait_until 和 boost::asio::streambuf

在 Boost.Asio 中同时使用 SSL 套接字和非 SSL 套接字?

Boost.Asio 的同步和并发数据结构模式

将 Boost.Log 与 Boost.Asio 服务一起使用