You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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,用以下命令验证:
    openssl x509 -in certificate.crt -noout -subject
    
    若CN不匹配,重新生成证书并指定CN为localhost。
  • 获取详细错误信息:修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:44:51