Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使POCO HTTPSClientSession发送请求时出现问题-证书验证失败_C++_Openssl_Poco Libraries - Fatal编程技术网

C++ 使POCO HTTPSClientSession发送请求时出现问题-证书验证失败

C++ 使POCO HTTPSClientSession发送请求时出现问题-证书验证失败,c++,openssl,poco-libraries,C++,Openssl,Poco Libraries,我正在尝试使用POCO库编写一个程序,向服务器发出HTTPS请求。出于测试目的,我正在连接到一个具有自签名证书的服务器,并且我希望允许客户端进行连接。为了让这种情况发生,我尝试安装了一个InvalidCertificateHandler,它是AcceptCertificateHandler的一个实例,我认为它会接受证书,即使它没有签名。以下是我使用的代码: try { Poco::SharedPtr<Poco::Net::InvalidCertificateHand

我正在尝试使用POCO库编写一个程序,向服务器发出HTTPS请求。出于测试目的,我正在连接到一个具有自签名证书的服务器,并且我希望允许客户端进行连接。为了让这种情况发生,我尝试安装了一个
InvalidCertificateHandler
,它是
AcceptCertificateHandler
的一个实例,我认为它会接受证书,即使它没有签名。以下是我使用的代码:

try {
            Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> pAcceptCertHandler =
                                             new Poco::Net::AcceptCertificateHandler(true);
            Poco::Net::Context::Ptr pContext =
                new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "",
                                       "","",Poco::Net::Context::VERIFY_RELAXED,
                                       9, true, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
            SSLManager::instance().initializeClient(NULL, pAcceptCertHandler, pContext);

            Poco::Net::HTTPSClientSession theSess(myHostName,myHostPort);

            // Create the HTTP request object
            Poco::Net::HTTPRequest request("POST",
                              "https://myservername.com/MockServlet/activateEnc","1.1");

            // Send the request
            std::cout << "Debug point A" << std::endl;
            std::ostream& aStream = theSess.sendRequest(request);
            std::cout << "Debug point B" << std::endl;
            if (aStream.fail()) {
                std::cout << "Fail to send HTTP request for activateEnc" << std::endl;
                return WSERR_CONNECTION_ERR;
            }   
        } catch (Poco::Exception& exc) {
            std::cout << "Exception caught while attempting to connect." << std::endl;
            std::cerr << exc.displayText() << std::endl;
            return WSERR_CONNECTION_ERR;
        }   
我的期望是,因为我正在使用AcceptCertificateHandler,所以即使证书无效,也会被接受。我可能做错了什么

几点注意:

  • 在上下文对象构造函数调用中,我为privateKeyFile、certificateFile和CalLocation参数传递空字符串。我这样做的原因是因为我认为作为客户机,我不需要私钥、客户机证书或证书颁发机构证书。也许这就是问题所在
  • 在对initializeClient的调用中,我将NULL作为PrivateKeyPasshraseHandler传递-因为我没有为客户端使用私钥
  • 在使用上下文对象之前,我不会调用Context::useCertificate()。文档说您需要调用userCertificate()或usePrivateKey(),但我不确定要传递什么,也不确定这是否是客户端所必需的,或者仅是服务器所必需的。也许这就是问题所在

  • 经过进一步试验,问题是服务器上的证书不仅是自签名的,而且已经过期。我尝试连接到不同的服务器,发现我可以。因此,即使使用AcceptCertificateHandler,库似乎也不会接受过期的证书


    更新证书使其不再过期后,可以进行连接。

    我发现,如果您通过主机名连接到服务器,则会发生相同的错误,该主机名不等于TLS(可能也是SSL)握手期间服务器证书中的主机名。在
    Poco::Net::HTTPSClientSession会话中使用正确的主机名(myHostName,myHostPort)解决此问题

    在我的例子中,正确的名称位于证书的
    CN
    字段中,我通过follow命令找到它(对于维基百科的exmaple):

    在输出中,我们看到:

    <...>
    Server certificate
    -----BEGIN CERTIFICATE-----
    MIIKCTCCCPGgAwIBAgIQARQZX2b6/4/WbhJJblFvTzANBgkqhkiG9w0BAQUFADBm
    <...>
    JW1fZqU0WxncxV8AfXeWfKzI1vkil45CJ4g++7U=
    -----END CERTIFICATE-----
    subject=/C=US/ST=California/L=San Francisco/O=Wikimedia Foundation, Inc./CN=*.wikipedia.org
    <...>
    
    
    服务器证书
    -----开始证书-----
    MIIKCTCCPGGAWIBAGIGQZX2B6/4/WbhJJblFvTzANBgkqhkiG9w0BAQUFADBm
    JW1fZqU0WxncxV8AfXeWfKzI1vkil45CJ4g++7U=
    -----结束证书-----
    主题= /C= U/ST =加利福尼亚/ L =旧金山/ O =维基媒体基金会,Inc. /CN=*.WikIOTIA.ORG
    
    就是这样:
    CN=*.wikipedia.org
    ,所以使用
    %domain%.wikipedia.org
    中的任何一个作为主机名应该是可以的


    顺便说一句,Poco中可能存在一些与SSL相关的错误的异常类,错误消息更为详细。

    我正是被这个问题困扰着,原来是证书CN。显然,在POCO中,您可以使用配置选项
    openSSL.client.extendedVerification=false
    pContext->enableExtendedCertificateVerification(false)禁用验证

    我在连接smtp.gmail.com时遇到此错误。。。有什么建议吗?你认为谷歌有过期的证书吗?我时断时续地得到它,但一天有几次,比如5次或6次。这里只是一个黑暗中的镜头:可能是因为谷歌的两步验证(见下面答案的评论):
    openssl s_client -connect en.wikipedia.org:443 -tls1 -state
    
    <...>
    Server certificate
    -----BEGIN CERTIFICATE-----
    MIIKCTCCCPGgAwIBAgIQARQZX2b6/4/WbhJJblFvTzANBgkqhkiG9w0BAQUFADBm
    <...>
    JW1fZqU0WxncxV8AfXeWfKzI1vkil45CJ4g++7U=
    -----END CERTIFICATE-----
    subject=/C=US/ST=California/L=San Francisco/O=Wikimedia Foundation, Inc./CN=*.wikipedia.org
    <...>