2012-08-31 62 views
2

我目前正在使用boost asio设置RESTful API。C++ Boost asio错误:无共享密码

从客户端连接通过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); 

之前任何人都曾经有过这样或得到它的工作?

回答

2

我有同样的问题,并以这种方式解决它。您必须为您的服务器生成一个私钥和一个证书文件。这里是这样做的过程:

// 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");

3

饲料未配置时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,消息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); 
} 

而且不要忘记创建为每个新连接新的数据流,上下文可以是相同的。

1

由于@asiocity指出,重要的部分是之前完全配置的SSL ::背景初始化的SSL ::流。

很难在初始化列表中初始化它们,同时仍然推迟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

我希望/希望一些构造,混入/模板技巧,可以让我只用一个自定义的初始化列表,而做到这一点比一个子类。