使用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
,上述代码应该可以访问服务器的证书:
当SSL / TLS会话成功完成初始握手时,会发出此信号。此时,没有传输用户数据。该信号可用于对证书链执行附加检查,例如,在网站证书发生更改时通知用户。如果回复与预期标准不匹配,则应通过连接到此信号的插槽调用QNetworkReply :: abort()来中止回复。可以使用QNetworkReply :: sslConfiguration()方法检查正在使用的SSL配置。
另外,来自documentation of QSslConfiguration::peerCertificate()
:
因为在握手阶段设置了对等证书,所以从连接到QSslSocket :: sslErrors()信号,QNetworkReply :: sslErrors()信号或QSslSocket :: encrypted的插槽访问对等证书是安全的。 ()信号。
但是,证书始终为空。上述代码的调试输出(在进入应用程序的事件循环之后)是:
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的信号;结果是一样的。
可以在https://bitbucket.org/leemes/ssltest 找到MCVE,随意克隆和摆弄:
git clone https://bitbucket.org/leemes/ssltest.git
我使用Qt 5.4.0和Qt 5.3.1进行了测试;结果是一样的。
答案 0 :(得分:2)
这是Qt中的一个错误,最高可达5.4.0。它已在Qt 5.4.1中修复。