基于C++ Poco API的SSL证书验证异常问题求助
Poco库HTTPS客户端请求抛出无详细信息的SSL Exception问题求助
问题背景
在Ubuntu系统下使用Visual Studio Code,基于Poco库开发C++服务端API及同机运行的独立HTTP请求客户端。已通过OpenSSL生成private2.key与certificate.crt证书文件并同步至服务端,服务端可正常启动,但客户端调用sendRequest发起HTTPS请求时,仅抛出无详细信息的SSL Exception: SSL Exception错误,无法定位具体问题。
服务端核心代码
//X509Certificate Poco::Net::Context::Ptr context = new Poco::Net::Context(Poco::Net::Context::SERVER_USE, "private2.key", "certificate.crt", "", Poco::Net::Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); Poco::Net::initializeSSL(); Poco::Net::SecureServerSocket svs(Poco::UInt16(port), 4, context); auto * httpServerParams = new Poco::Net::HTTPServerParams(); httpServerParams->setMaxQueued(250); httpServerParams->setMaxThreads(50); Poco::Net::HTTPServer httpServer(getRouter(), svs, httpServerParams); std::cout << "Poco Restful Web Service started and running." << std::endl; std::cout << "Type http://" << endpoint << ":" << port << " to use it or "; std::cout << "type CRLT+C to finish it." << std::endl; httpServer.start(); waitForTerminationRequest(); httpServer.stop(); std::cout << "\nPoco Restful Web Service stopped. \nGoodbye." << std::endl; return Poco::Util::Application::EXIT_OK;
客户端核心代码
#include <Poco/Net/HTTPClientSession.h> #include <Poco/Net/HTTPSClientSession.h> #include <Poco/Net/HTTPRequest.h> #include <Poco/Net/HTTPResponse.h> #include <Poco/Net/HTTPBasicCredentials.h> #include <Poco/Net/SSLManager.h> #include <Poco/Path.h> #include <Poco/URI.h> #include <Poco/JSON/Object.h> #include <Poco/Net/X509Certificate.h> #include <Poco/Net/Context.h> #include <Poco/Net/SSLException.h> #include <iostream> #include <string> using namespace Poco::Net; using namespace Poco; using namespace std; int main() { Poco::Net::initializeSSL(); // prepare session Poco::URI uri("https://localhost:9090/postRequest"); // create request Poco::Net::HTTPRequest req(HTTPRequest::HTTP_POST, uri.getPathAndQuery(),HTTPRequest::HTTP_1_1); Poco::JSON::Object object1(Poco::JSON_PRESERVE_KEY_ORDER); // Creating object to preserve the insertion order object1.set("name", "John"); // adding a key-value pair object1.set("city", "Rome"); std::stringstream ss; object1.stringify(ss); req.setContentType("application/json"); req.setContentLength(ss.str().size()); //Certificate X509Certificate x590certificate("certificate.crt"); Context::Ptr context = new Poco::Net::Context(Context::CLIENT_USE, "private2.key", "certificate.crt", "", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); //Context::Ptr context = SSLManager::instance().defaultClientContext(); // send request try { Poco::Net::initializeSSL(); Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort(), context); std::ostream& myOStream = session.sendRequest(req); object1.stringify(myOStream); // get response Poco::Net::HTTPResponse res; session.receiveResponse(res); std::cout << "Response Status = " << res.getStatus() << std::endl; std::cout << "Response Reason = " << res.getReason() << std::endl; Poco::Net::uninitializeSSL(); } catch (const Poco::Net::SSLException& ex) { std::cerr << "SSL Exception: " << ex.what() << std::endl; } return 0; }
证书生成命令
openssl genrsa -aes128 -out private.key 2048 openssl rsa -in private.key -out private2.key openssl req -new -days 365 -key private2.key -out request.csr -config openssl.cnf openssl x509 -req -in request.csr -out certificate.crt -signkey private2.key -days 365 -extensions v3_req -extfile openssl.cnf
排查与解决建议
- 修复重复初始化SSL问题:客户端
main函数开头已调用Poco::Net::initializeSSL(),try块内的重复调用会导致上下文冲突,直接删除该重复代码。 - 调整客户端SSL上下文:客户端无需加载私钥
private2.key,只需指定信任的服务端证书即可,修改Context初始化代码:
测试阶段可临时关闭证书验证(生产环境禁用):Context::Ptr context = new Poco::Net::Context(Context::CLIENT_USE, "", "certificate.crt", "", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");Context::Ptr context = new Poco::Net::Context(Context::CLIENT_USE, "", "", "", Context::VERIFY_NONE, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); - 检查证书CN字段匹配:生成证书时
Common Name (CN)必须设为localhost,用以下命令验证:
若CN不匹配,重新生成证书并指定CN为openssl x509 -in certificate.crt -noout -subjectlocalhost。 - 获取详细错误信息:修改catch块,利用
ex.displayText()打印完整错误栈:catch (const Poco::Net::SSLException& ex) { std::cerr << "SSL Exception: " << ex.what() << std::endl; std::cerr << "详细错误信息: " << ex.displayText() << std::endl; } - 确认证书路径有效性:使用绝对路径指定证书位置,避免程序因相对路径找不到文件报错。
内容的提问来源于stack exchange,提问作者MrJay
相关产品推荐
相关产品推荐

