2

我目前正在使用 boost asio 设置 RESTful API。

通过 HTTP 从客户端连接可以正常工作。但是,如果我尝试通过 HTTPS 连接,我会在服务器端收到错误消息:“没有共享密码”。该错误似乎来自 openssl 实现,但我不知道该怎么做。我的第一个猜测是没有设置密码算法,但我看不出如何在 asio.

这是我在代码中输入的内容以及发生错误的位置:

auto acceptHandler = boost::bind(&self::onAccept, this, connection,
                                 boost::asio::placeholders::error);
connection->async_accept(m_acceptor, acceptHandler);

m_sslContext.set_options(
        context::default_workarounds | context::no_sslv2 | context::single_dh_use);
m_sslContext.use_certificate_file(filename, context::pem);
m_sslContext.use_private_key_file(filename, context::pem);

有人以前有过这个或让它工作吗?

4

3 回答 3

5

我遇到了同样的问题并以这种方式解决了。您必须为您的服务器生成私钥和证书文件。这是这样做的程序:

// Generate a new ssl private key :
$openssl genrsa -out privkey.pem 1024

// Create a certificate signing request using your new key
$openssl req -new -key privkey.pem -out certreq.csr

// Self-sign your CSR with your own private key:
$openssl x509 -req -days 3650 -in certreq.csr -signkey privkey.pem -out newcert.pem

// Install the signed certificate and private key for use by an ssl server
// This allows you to use a single file for certificate and private key
$( openssl x509 -in newcert.pem; cat privkey.pem ) > server.pem

// If you use a dh temp file :
$openssl dhparam -outform PEM -out dh512.pem 512

然后,将server.pemdh512.pem文件复制到您的服务器执行目录中。

如果您使用 tmp dh 文件,您还必须添加这行代码m_sslContext.use_tmp_dh_file("dh512.pem");

于 2012-09-19T10:18:38.023 回答
4

boost::asio::ssl::context将未配置的对象提供给对象构造函数时出现相同的错误boost::asio::ssl::stream,然后将其用作接受的结果套接字:

server()
    : m_acceptor(/*args*/)
    , m_context(boost::asio::ssl::context::tlsv1_server)
    , m_stream(m_io_service, m_context)
{
    // `m_context` configuring, BUT `m_stream` is unaffected
    m_acceptor.async_accept(m_stream.lowest_layer(), accept_result_handler);
}
// run somewhere `m_io_service.run()`, or other processor of `async` operations.

在实际接受连接并在其上处理握手之后,握手处理程序接收boost::system::error_code值为 336109761 和 message no shared cipher

所以首先创建和配置boost::asio::ssl::context,然后boost::asio::ssl::stream用它构建:

typedef boost::asio::ip::tcp::socket socket_type;
typedef boost::asio::ssl::stream<socket_type> stream_type;

std::shared_ptr<stream_type> m_stream;

server()
    : m_acceptor(/*args*/)
    , m_context(boost::asio::ssl::context::tlsv1_server)
{
    // `m_context` configuring
    m_stream = std::make_shared<stream_type>(m_io_service, m_context);
    m_acceptor.async_accept(m_stream->lowest_layer(), accept_result_handler);
}

并且不要忘记为每个新连接创建新流,上下文可以相同。

于 2013-10-25T08:23:46.627 回答
1

正如@asiocity 指出的那样,重要的部分是在初始化 ssl::stream之前完全配置ssl::context 。

很难在初始化列表中同时初始化它们,同时仍然推迟 ssl::stream 直到 ssl::context 完全配置。

我使用的一种方法是子类化 ssl::context 并覆盖构造函数,以便在初始化 ssl::stream 之前可以在初始化列表中对其进行完全配置。

例如

class server_context : public boost::asio::ssl::context {
  public: server_context(boost::asio::ssl::context::method m, std::string certfile);
};

...

server_context::server_context(boost::asio::ssl::context::method m, std::string certfile)
: boost::asio::ssl::context(m)
{
  use_private_key_file(certfile);
  use_certificate_chain_file(certfile);
}

...

class myclass {
  private:
    server_context : ssl_context_;
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> stream_;
  public:
    myclass(boost::asio::ip::tcp::socket&, std::string certfile);

...

myclass::myclass(std::string certfile) 
: ssl_context_(boost::asio::ssl::context::sslv23, certfile),
  stream_(socket, ssl_context_) 
{
  ...
}

然而,避免 shared_ptr 似乎需要做很多工作

我希望/希望有一些构造函数-mixin/模板技巧,它允许我只使用自定义初始化列表而不是子类来做到这一点。

于 2015-10-14T12:16:19.287 回答