C++ 使POCO HTTPSClientSession发送请求时出现问题-证书验证失败
我正在尝试使用POCO库编写一个程序,向服务器发出HTTPS请求。出于测试目的,我正在连接到一个具有自签名证书的服务器,并且我希望允许客户端进行连接。为了让这种情况发生,我尝试安装了一个C++ 使POCO HTTPSClientSession发送请求时出现问题-证书验证失败,c++,openssl,poco-libraries,C++,Openssl,Poco Libraries,我正在尝试使用POCO库编写一个程序,向服务器发出HTTPS请求。出于测试目的,我正在连接到一个具有自签名证书的服务器,并且我希望允许客户端进行连接。为了让这种情况发生,我尝试安装了一个InvalidCertificateHandler,它是AcceptCertificateHandler的一个实例,我认为它会接受证书,即使它没有签名。以下是我使用的代码: try { Poco::SharedPtr<Poco::Net::InvalidCertificateHand
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,所以即使证书无效,也会被接受。我可能做错了什么
几点注意:
经过进一步试验,问题是服务器上的证书不仅是自签名的,而且已经过期。我尝试连接到不同的服务器,发现我可以。因此,即使使用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
<...>