尝试连接自签名证书时出现 QT 5.5 SSLHandshakeFailedError
QT 5.5 SSLHandshakeFailedError when trying connect with a self signed certificate
我使用以下代码尝试建立与远程主机的连接。
客户端必须使用自签名证书进行身份验证才能创建有效的 SSL 连接:
QRemoteProxyCommunication::QRemoteProxyCommunication(QObject *parent) : QObject(parent) {
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request;
QFile certFile("/path/to/file/clientcert.p12");
certFile.open(QFile::ReadOnly);
QSslCertificate certificate;
QSslKey key;
QList<QSslCertificate> importedCerts;
bool imported = QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString(""));
qDebug() << "Imported: " << imported;
QSslConfiguration config = request.sslConfiguration();
config.setCaCertificates(importedCerts);
config.setProtocol(QSsl::AnyProtocol);
config.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(config);
request.setUrl(QUrl("https://www.url.com"));
reply = manager->get(request);;
qDebug() << " Certs: " << certificate;
qDebug() << reply->error();
qDebug() << reply->errorString();
connect(reply, SIGNAL(readyRead()), this, SLOT(replyReadyRead()));
connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyNetworkError(QNetworkReply::NetworkError)));
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>)),
this, SLOT(errors(QNetworkReply*, const QList<QSslError>)));
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>)),
this, SLOT(errors(QNetworkReply*, const QList<QSslError>)));
}
void QRemoteProxyCommunication::replyNetworkError(QNetworkReply::NetworkError code) {
qDebug() << "Network error => " << code;
}
但我总是收到错误信息:
Network error => QNetworkReply::NetworkError(SslHandshakeFailedError)
在 replyNetworkError
插槽中。
此外,插槽 errors
未被调用。
行QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString(""));
returnstrue
.
如果我在 Chrome 浏览器中添加 p12 证书文件并尝试打开主机,它工作正常。
此外,如果我尝试调用 request.setUrl(QUrl("https://www.test.de"));
,则会调用 readyRead()
信号,我可以读取响应内容。
我的实现有什么问题?
问题是在 importPkcs12
函数中作为参数传递的引用对象(如 QSslKey
)没有在 QSslConfiguration
config 对象中明确设置。
QFile certFile("/path/to/file/clientcert.p12");
certFile.open(QFile::ReadOnly);
QSslCertificate certificate;
QSslKey key;
QList<QSslCertificate> importedCerts;
bool imported = QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString("xxxx"));
QSslConfiguration config = request.sslConfiguration();
config.setCaCertificates(importedCerts);
config.setLocalCertificate(certificate);
config.setPrivateKey(key);
config.setProtocol(QSsl::AnyProtocol);
config.setPeerVerifyMode(QSslSocket::VerifyNone);
添加缺失的线路后,连接建立成功。
我使用以下代码尝试建立与远程主机的连接。
客户端必须使用自签名证书进行身份验证才能创建有效的 SSL 连接:
QRemoteProxyCommunication::QRemoteProxyCommunication(QObject *parent) : QObject(parent) {
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request;
QFile certFile("/path/to/file/clientcert.p12");
certFile.open(QFile::ReadOnly);
QSslCertificate certificate;
QSslKey key;
QList<QSslCertificate> importedCerts;
bool imported = QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString(""));
qDebug() << "Imported: " << imported;
QSslConfiguration config = request.sslConfiguration();
config.setCaCertificates(importedCerts);
config.setProtocol(QSsl::AnyProtocol);
config.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(config);
request.setUrl(QUrl("https://www.url.com"));
reply = manager->get(request);;
qDebug() << " Certs: " << certificate;
qDebug() << reply->error();
qDebug() << reply->errorString();
connect(reply, SIGNAL(readyRead()), this, SLOT(replyReadyRead()));
connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyNetworkError(QNetworkReply::NetworkError)));
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>)),
this, SLOT(errors(QNetworkReply*, const QList<QSslError>)));
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>)),
this, SLOT(errors(QNetworkReply*, const QList<QSslError>)));
}
void QRemoteProxyCommunication::replyNetworkError(QNetworkReply::NetworkError code) {
qDebug() << "Network error => " << code;
}
但我总是收到错误信息:
Network error => QNetworkReply::NetworkError(SslHandshakeFailedError)
在 replyNetworkError
插槽中。
此外,插槽 errors
未被调用。
行QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString(""));
returnstrue
.
如果我在 Chrome 浏览器中添加 p12 证书文件并尝试打开主机,它工作正常。
此外,如果我尝试调用 request.setUrl(QUrl("https://www.test.de"));
,则会调用 readyRead()
信号,我可以读取响应内容。
我的实现有什么问题?
问题是在 importPkcs12
函数中作为参数传递的引用对象(如 QSslKey
)没有在 QSslConfiguration
config 对象中明确设置。
QFile certFile("/path/to/file/clientcert.p12");
certFile.open(QFile::ReadOnly);
QSslCertificate certificate;
QSslKey key;
QList<QSslCertificate> importedCerts;
bool imported = QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString("xxxx"));
QSslConfiguration config = request.sslConfiguration();
config.setCaCertificates(importedCerts);
config.setLocalCertificate(certificate);
config.setPrivateKey(key);
config.setProtocol(QSsl::AnyProtocol);
config.setPeerVerifyMode(QSslSocket::VerifyNone);
添加缺失的线路后,连接建立成功。