无法获取POCO HTTPSClientSession发送请求 - 证书验证失败 [英] Trouble getting POCO HTTPSClientSession to send a request - certificate verify failed

查看:2505
本文介绍了无法获取POCO HTTPSClientSession发送请求 - 证书验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用POCO库来编写一个向服务器发出HTTPS请求的程序。为了测试的目的,我连接到一个具有自签名证书的服务器,我想允许客户端连接。为了允许这种情况,我试图安装 InvalidCertificateHandler 这是 AcceptCertificateHandler 的一个实例 - 我想将接受证书,即使它没有签名。这里是我使用的代码:

I'm trying to use the POCO libraries to write a program that makes an HTTPS request to a server. For testing purposes, I'm connecting to a server which has a self-signed certificate, and I want to allow the client to connect anyway. To allow that to happen, I've attempted to install an InvalidCertificateHandler which is an instance of AcceptCertificateHandler - which I thought would accept the certificate even though it's not signed. Here's the code I'm using:

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;
        }   



当我运行这个代码,我得到以下输出:

When I run this code, I get the following output:

Debug point A
Exception caught while attempting to connect.
Certificate validation error: Unacceptable certificate from myservername.com: application verification failure

因为我使用AcceptCertificateHandler,证书将被接受,即使它是无效的。

My expectation was that since I'm using the AcceptCertificateHandler, the certificate would be accepted even though it is not valid. What might I be doing wrong?

有几个注意事项:


  1. 上下文对象构造函数调用,我传递空字符串privateKeyFile,certificateFile和caLocation参数。我这样做的原因是因为我认为作为客户端我不需要私钥,客户端证书或证书颁发机构证书。也许这是问题?

  2. 在调用initializeClient时,我传递NULL作为PrivateKeyPasshraseHandler - 因为我没有使用客户端的私钥。

  3. 我在使用Context对象之前不调用Context :: useCertificate()。文档说,你需要调用userCertificate()或usePrivateKey(),但我不知道该传递什么,或者这是客户端或仅服务器需要。也许这是问题?


推荐答案

我发现如果连接到服务器由hostname不等于在TLS(可能是SSL过)握手期间进入服务器的证书中的主机名。在中使用正确的主机名> Poco :: Net :: HTTPSClientSession theSess(myHostName,myHostPort); 解决此问题。

I found that same error occurs if you connect to server by hostname which is not equal to hostname coming in certificate of the server during the TLS (probably SSL too) handshake. Using right hostname in Poco::Net::HTTPSClientSession theSess(myHostName, myHostPort); solve this problem.

在我的例子中,正确的名称是在字段 CN 的证书,我发现它通过命令(例如维基百科):

In my case right name was in field CN of certificate, I found it by follow command (for exmaple for wikipedia):

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
<...>

有: CN = *。wikipedia.org ,所以使用%domain%.wikipedia.org 作为主机名应该是确定。

There is it: CN=*.wikipedia.org, so using any of %domain%.wikipedia.org as hostname should be ok.

顺便说一下,在Poco中可能有一些与SSL相关的错误的异常类,并显示更详细的错误消息。

P.S. By the way, there may be some exception class for SSL related errors in Poco with more verbose error message.

这篇关于无法获取POCO HTTPSClientSession发送请求 - 证书验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆