Boost Asio https同步调用-错误代码400错误请求
Boost Asio https synchronous call- Error code 400 bad request
我们正在从 http 迁移到 https boost asio sysnchornous 调用,我正在使用以下代码通过 ssl 证书验证进行 https 同步调用。我们获得了证书颁发机构颁发的客户端证书,并以 .pem 格式下载了它。我们有以下问题:
1.) 如何在boost asio中加载证书;我们可以使用以下路径加载证书文件吗:
boost::asio::streambuf response_;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::verify_peer);
//ctx.set_default_verify_paths();
**ctx.load_verify_file("/tmp/cacert.pem");**
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service,ctx);
2.)同步https调用中peer验证的目的是什么;我们可以像下面这样在没有同行验证的情况下进行握手吗?
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
socket.handshake(boost::asio::ssl::stream_base::client);
3.) 当我使用 ssl 验证访问端点 url 时,我收到错误请求错误代码 400。请验证以下代码,如果我缺少与 ssl 证书部分相关的内容,请告诉我(注意:请求 header 并且消息在更改为 https 之前工作正常):
boost::asio::streambuf response_;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::verify_peer);
ctx.load_verify_file("/tmp/cacert.pem");
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service,ctx);
std::ostream request_stream(&request_);
request_stream << "POST " << server_endpoint << " HTTP/1.1\n";
request_stream << "Host: " << hostname << "\n";
request_stream << "Accept: */*\n";
request_stream << authorization_token << "\n";
request_stream << client_name << "\n";
request_stream << "Content-Length: " << req_str.length() << "\n";
request_stream << "Content-Type: application/x-www-form-urlencoded \n";
request_stream << "Connection: close\r\n\r\n";
request_stream << req_str << "\n";
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
socket.handshake(boost::asio::ssl::stream_base::client);
谢谢
您的请求有误:)
HTTP 要求 CR+LF 行结束。所以,无论你在哪里单独使用 \n
,它都需要是 \r\n
.
完整的工作示例
我完成了你的样本以测试它。我可能(?)已经通过使用
回答了您关于证书的问题 - 或者部分回答了
//ctx.load_verify_file("ca.pem");
ctx.add_verify_path("/etc/ssl/certs");
这使用大多数 Linux 系统将存储默认证书库的位置,这意味着通常受信任的证书 system-wide。
清单:
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>
using boost::asio::ip::tcp;
// https://postman-echo.com/post see https://docs.postman-echo.com/?version=latest
static const std::string
server_endpoint = "/post",
hostname = "postman-echo.com",
port_no = "443",
authorization_token =
"Auth: "
"c3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGF1dGhvcml6YXRpb"
"25fdG9rZW4gPSAiQXV0aDogIj"
"sK",
client_name = "User-Agent: demo program 0.01",
req_str = R"(name=blabla&password=bloblo)";
int main() {
boost::asio::io_service io_service;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::verify_peer);
//ctx.load_verify_file("ca.pem");
ctx.add_verify_path("/etc/ssl/certs");
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service,
ctx);
{
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
}
{
boost::asio::streambuf request_;
socket.handshake(boost::asio::ssl::stream_base::client);
{
std::ostream request_stream(&request_);
request_stream << "POST " << server_endpoint << " HTTP/1.1\r\n";
request_stream << "Host: " << hostname << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << authorization_token << "\r\n";
request_stream << client_name << "\r\n";
request_stream << "Content-Length: " << req_str.length() << "\r\n";
request_stream << "Content-Type: application/x-www-form-urlencoded \r\n";
request_stream << "Connection: close\r\n\r\n";
request_stream << req_str << "\r\n";
} // forces flush()
//std::cout << &request_;
//std::cout << "--------" << std::endl;
write(socket, request_);
//socket.lowest_layer().shutdown(tcp::socket::shutdown_send);
}
{
boost::asio::streambuf response_;
boost::system::error_code ec;
read(socket, response_, ec);
std::cout << "ec: " << ec.message() << "\n";
std::cout << &response_ << "\n";
}
}
它使用 the postman online sample service 并打印:
ec: stream truncated
HTTP/1.1 200 OK
Date: Fri, 07 Aug 2020 16:23:04 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 519
Connection: close
ETag: W/"207-JMbCSlSXSCnZPMi2WQ8SuP+keys"
Vary: Accept-Encoding
set-cookie: sails.sid=s%3AFBof16WW2UeR2Si6dtf9WRUfKiJbpIhH.O2YgXPhClKJKnJ0bmTFuyl%2FyKNyS3oADFbDHHt4UKX8; Path=/; HttpOnly
{"args":{},"data":"","files":{},"form":{"name":"blabla","password":"bloblo"},"headers":{"x-forwarded-proto":"https","x-forwarded-port":"443","host":"postman-echo.com","x-amzn-trace-id":"Root=1-5f2d7fe8-0348dee860e746ac828f4d80","content-length":"27","accept":"*/*","auth":"c3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGF1dGhvcml6YXRpb25fdG9rZW4gPSAiQXV0aDogIjsK","user-agent":"demo program 0.01","content-type":"application/x-www-form-urlencoded"},"json":{"name":"blabla","password":"bloblo"},"url":"https://postman-echo.com/post"}
The stream truncated
is probably expected: https://github.com/boostorg/beast/issues/38
我们正在从 http 迁移到 https boost asio sysnchornous 调用,我正在使用以下代码通过 ssl 证书验证进行 https 同步调用。我们获得了证书颁发机构颁发的客户端证书,并以 .pem 格式下载了它。我们有以下问题:
1.) 如何在boost asio中加载证书;我们可以使用以下路径加载证书文件吗:
boost::asio::streambuf response_;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::verify_peer);
//ctx.set_default_verify_paths();
**ctx.load_verify_file("/tmp/cacert.pem");**
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service,ctx);
2.)同步https调用中peer验证的目的是什么;我们可以像下面这样在没有同行验证的情况下进行握手吗?
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
socket.handshake(boost::asio::ssl::stream_base::client);
3.) 当我使用 ssl 验证访问端点 url 时,我收到错误请求错误代码 400。请验证以下代码,如果我缺少与 ssl 证书部分相关的内容,请告诉我(注意:请求 header 并且消息在更改为 https 之前工作正常):
boost::asio::streambuf response_;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::verify_peer);
ctx.load_verify_file("/tmp/cacert.pem");
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service,ctx);
std::ostream request_stream(&request_);
request_stream << "POST " << server_endpoint << " HTTP/1.1\n";
request_stream << "Host: " << hostname << "\n";
request_stream << "Accept: */*\n";
request_stream << authorization_token << "\n";
request_stream << client_name << "\n";
request_stream << "Content-Length: " << req_str.length() << "\n";
request_stream << "Content-Type: application/x-www-form-urlencoded \n";
request_stream << "Connection: close\r\n\r\n";
request_stream << req_str << "\n";
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
socket.handshake(boost::asio::ssl::stream_base::client);
谢谢
您的请求有误:)
HTTP 要求 CR+LF 行结束。所以,无论你在哪里单独使用 \n
,它都需要是 \r\n
.
完整的工作示例
我完成了你的样本以测试它。我可能(?)已经通过使用
回答了您关于证书的问题 - 或者部分回答了 //ctx.load_verify_file("ca.pem");
ctx.add_verify_path("/etc/ssl/certs");
这使用大多数 Linux 系统将存储默认证书库的位置,这意味着通常受信任的证书 system-wide。
清单:
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>
using boost::asio::ip::tcp;
// https://postman-echo.com/post see https://docs.postman-echo.com/?version=latest
static const std::string
server_endpoint = "/post",
hostname = "postman-echo.com",
port_no = "443",
authorization_token =
"Auth: "
"c3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGF1dGhvcml6YXRpb"
"25fdG9rZW4gPSAiQXV0aDogIj"
"sK",
client_name = "User-Agent: demo program 0.01",
req_str = R"(name=blabla&password=bloblo)";
int main() {
boost::asio::io_service io_service;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::verify_peer);
//ctx.load_verify_file("ca.pem");
ctx.add_verify_path("/etc/ssl/certs");
ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service,
ctx);
{
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, port_no);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
boost::system::error_code error = boost::asio::error::host_not_found;
boost::asio::connect(socket.lowest_layer(), endpoint_iterator, error);
}
{
boost::asio::streambuf request_;
socket.handshake(boost::asio::ssl::stream_base::client);
{
std::ostream request_stream(&request_);
request_stream << "POST " << server_endpoint << " HTTP/1.1\r\n";
request_stream << "Host: " << hostname << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << authorization_token << "\r\n";
request_stream << client_name << "\r\n";
request_stream << "Content-Length: " << req_str.length() << "\r\n";
request_stream << "Content-Type: application/x-www-form-urlencoded \r\n";
request_stream << "Connection: close\r\n\r\n";
request_stream << req_str << "\r\n";
} // forces flush()
//std::cout << &request_;
//std::cout << "--------" << std::endl;
write(socket, request_);
//socket.lowest_layer().shutdown(tcp::socket::shutdown_send);
}
{
boost::asio::streambuf response_;
boost::system::error_code ec;
read(socket, response_, ec);
std::cout << "ec: " << ec.message() << "\n";
std::cout << &response_ << "\n";
}
}
它使用 the postman online sample service 并打印:
ec: stream truncated
HTTP/1.1 200 OK
Date: Fri, 07 Aug 2020 16:23:04 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 519
Connection: close
ETag: W/"207-JMbCSlSXSCnZPMi2WQ8SuP+keys"
Vary: Accept-Encoding
set-cookie: sails.sid=s%3AFBof16WW2UeR2Si6dtf9WRUfKiJbpIhH.O2YgXPhClKJKnJ0bmTFuyl%2FyKNyS3oADFbDHHt4UKX8; Path=/; HttpOnly
{"args":{},"data":"","files":{},"form":{"name":"blabla","password":"bloblo"},"headers":{"x-forwarded-proto":"https","x-forwarded-port":"443","host":"postman-echo.com","x-amzn-trace-id":"Root=1-5f2d7fe8-0348dee860e746ac828f4d80","content-length":"27","accept":"*/*","auth":"c3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGF1dGhvcml6YXRpb25fdG9rZW4gPSAiQXV0aDogIjsK","user-agent":"demo program 0.01","content-type":"application/x-www-form-urlencoded"},"json":{"name":"blabla","password":"bloblo"},"url":"https://postman-echo.com/post"}
The
stream truncated
is probably expected: https://github.com/boostorg/beast/issues/38