使用Boost.Asio和OpenSSL的HTTPS请求

Maa*_*ten 14 c++ https boost openssl boost-asio

我正在尝试从我的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");
Run Code Online (Sandbox Code Playgroud)

我将验证设置为none,否则握手失败.我不确定这是否是mtgox的问题,或者这个实现是非常严格的,因为当我将证书打印到屏幕上时它看起来是合法的(当访问自动收报机页面时,chrome没有问题).

socket_.set_verify_mode(boost::asio::ssl::context::verify_none);
Run Code Online (Sandbox Code Playgroud)

这是我发送的请求:

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));
Run Code Online (Sandbox Code Playgroud)

(完整代码: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
Run Code Online (Sandbox Code Playgroud)

我是否朝着正确的方向前进?错误消息并不能真正描述问题,我不知道哪个步骤我做错了.

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

curl --trace-ascii out.txt https://mtgox.com/api/0/data/ticker.php
Run Code Online (Sandbox Code Playgroud)

(完整输出:http://pastebin.com/Rzp0RnAK)验证期间失败.当我连接"unsafe"参数时

curl --trace-ascii out.txt -k https://mtgox.com/api/0/data/ticker.php
Run Code Online (Sandbox Code Playgroud)

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

一切正常.

固定:

  1. 我修复了HTTP标头中的拼写错误
  2. 我添加了根证书并重新启用了SSL验证.

Bla*_*ade 10

简而言之:

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

  2. 也许OpenSSL没有服务器使用的根证书,这与Chrome不同,这就是验证失败的原因.

细节:

  1. 鉴于工作和非工作工具,您应该始终比较正在发生的事情.在这里你有cURL的输出和你的要求 - 比较它们显示了许多不同之处; 通常,即使使用加密连接,您也可以使用强大的数据包嗅探器,如Wireshark,它可以从数据包中尽可能多地解码信息.这里可以看到服务器实际上发送的数据包较少(我期待); 另一种可能性是你的客户端没有得到服务器发送的数据(比如因为客户端有一些bug).

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