在使用Qt执行HTTPS请求时,我尝试在SSL握手后获取对等方的证书,以便跟踪证书中的未来更改.
QNetworkAccessManager nam;
nam.get(QNetworkRequest(QUrl("https://google.com/"))); // example URL
QObject::connect(&nam, &QNetworkAccessManager::encrypted, [](QNetworkReply *reply){
qDebug() << reply->sslConfiguration().peerCertificate();
});
根据documentation of QNetworkAccessManager::encrypted
,上面的代码应该可以访问服务器的证书:
This signal is emitted when an SSL/TLS session has successfully completed the initial handshake. At this point, no user data has been transmitted. The signal can be used to perform additional checks on the certificate chain, for example to notify users when the certificate for a website has changed. If the reply does not match the expected criteria then it should be aborted by calling QNetworkReply::abort() by a slot connected to this signal. The SSL configuration in use can be inspected using the QNetworkReply::sslConfiguration() method.
另外,从documentation of QSslConfiguration::peerCertificate()
开始:
Because the peer certificate is set during the handshake phase, it is safe to access the peer certificate from a slot connected to the QSslSocket::sslErrors() signal, QNetworkReply::sslErrors() signal, or the QSslSocket::encrypted() signal.
但是,证书始终为空.上述代码的调试输出(在进入应用程序的事件循环之后)是:
QSslCertificate( "" , "" , "1B2M2Y8AsgTpgAmY7PhCfg==" , () , () , QMap() , QDateTime(" Qt::LocalTime") , QDateTime(" Qt::LocalTime") )
另一方面,如果遇到SSL错误,并且我连接到sslErrors,我会获得证书.例如,对于Ubuntu / Apache下的默认证书,由于证书中缺少主机名而未被Qt接受,我得到“https:// localhost”以下内容:
QSslCertificate( "3" , "95:b0:93:f2:16:bb:22:cb" , "cXB6WctE7oZsrvZLU2BWUw==" , () , () , QMap() , QDateTime("2014-07-10 23:04:06.000 UTC Qt::UTC") , QDateTime("2024-07-07 23:04:06.000 UTC Qt::UTC") )
SSL握手成功后如何获取证书?
我测试了QNetworkAccessManager的信号以及QNetworkReply的信号;结果是一样的.
MCVE可以在https://bitbucket.org/leemes/ssltest找到,随意克隆和拨弄:
git clone https://bitbucket.org/leemes/ssltest.git
我用Qt 5.4.0和Qt 5.3.1进行了测试;结果是一样的.
最佳答案 这是Qt中的一个错误,最高可达5.4.0.它已在Qt 5.4.1中修复.