Boost Asio https同步呼叫-错误代码400错误的请求 [英] Boost Asio https synchronous call- Error code 400 bad request

查看:155
本文介绍了Boost Asio https同步呼叫-错误代码400错误的请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在从http迁移到https boost asio sysnchornous调用,我正在使用以下代码通过SSL证书验证进行https同步调用.我们获得了由证书颁发机构颁发的客户证书,并以.pem格式下载了该证书.我们有以下问题:

we are migrating from http to https boost asio sysnchornous call and I am using the below code to make https synchoronous call with ssl certificate validation. we got our client certificate issued by certiticate authority and we downloaded it in .pem format. we have the following questions:

1.)如何在boost asio中加载证书;我们可以使用以下路径加载证书文件吗?

1.) how to load the certificates in boost asio; can we load the certificate file with the path as below:

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呼叫中对等验证的目的是什么;无需如下所示的同行验证,我们可以握手吗?

2.)what is the purpose of peer verification in synchoronous https call; can we make handshake without peer verification as like below?

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证书部分有关(请注意:在更改为https之前,请求标头和消息工作正常):

3.) I am getting Bad request Error code 400 when i am hitting endpoint url with ssl verification. Please verify the below code and let me know if i am missing related to ssl certificate part(note: request header and message worked fine before changing to 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.

HTTP requires CR+LF line ends. So, everywhere you use \n alone it needs to be \r\n.

我完成了您的样品以进行测试.我可能(?)已通过使用

I completed your sample in order to test it. I may (?) have answered your question about certificates - or partly - by using

    //ctx.load_verify_file("ca.pem");
    ctx.add_verify_path("/etc/ssl/certs");

这使用大多数Linux系统存储默认证书存储的位置,这意味着通常在系统范围内都是受信任的证书.

This uses the location where most Linux systems will store the default certificate store, meaning the certificates that are typically trusted 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";
    }
}

它使用邮递员在线示例服务并打印:

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"}

stream truncated可能是预期的: https://github.com/boostorg/beast/issues/38

这篇关于Boost Asio https同步呼叫-错误代码400错误的请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆