我正在尝试使用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;
}
当我运行此代码时,我得到以下输出:
Debug point A
Exception caught while attempting to connect.
Certificate validation error: Unacceptable certificate from myservername.com: application verification failure
我的期望是,因为我正在使用AcceptCertificateHandler,即使证书无效,证书也会被接受。我可能做错了什么?
一对夫妇注意到:
答案 0 :(得分:3)
我发现如果你通过hostname连接到服务器会发生同样的错误,这不等于在TLS(可能是SSL)握手期间进入服务器证书的主机名。在Poco::Net::HTTPSClientSession theSess(myHostName, myHostPort);
中使用正确的主机名解决了这个问题。
在我的情况下,正确的名称是在证书的字段CN
中,我通过follow命令找到它(对于维基百科的例子):
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
作为主机名应该没问题。
P.S。顺便说一句,Poco中可能存在一些与SSL相关的错误的异常类,并且有更详细的错误消息。
答案 1 :(得分:0)
经过进一步的实验,问题证明是服务器上的证书不仅是自签名的,而且也是过期的。我尝试连接到不同的服务器,发现我能够。因此,即使使用AcceptCertificateHandler,该库似乎也不会接受过期的证书。
更新证书以使其不再过期后,能够建立连接。
答案 2 :(得分:0)
我完全被这个问题困住了,原来是证书CN。显然,在POCO中,您可以使用配置选项openSSL.client.extendedVerification = false
或pContext->enableExtendedCertificateVerification(false);