我需要与需要本地证书(.crt文件)的服务器交换数据。我试试这个:
loginRequest = QNetworkRequest(QUrl("https://somesite.com/login"));
QSslConfiguration sslConf = loginRequest.sslConfiguration();
QList<QSslCertificate> certs = QSslCertificate::fromPath(Preferences::certificatePath());
qDebug() << certs.first().issuerInfo(QSslCertificate::Organization); // prints name
sslConf.setLocalCertificate(certs.first());
qDebug() << "is valid " << sslConf.localCertificate().isValid(); // true
qDebug() << "is null " << sslConf.localCertificate().isNull(); // false
qDebug() << "protocol " << sslConf.protocol(); // 0
sslConf.setProtocol(QSsl::SslV3); // i also tried Qssl::AnyProtocol
qDebug() << "protocol " << sslConf.protocol(); // 0
// if i uncomment these i expect everithing to work
//QSslConfiguration::setDefaultConfiguration(sslConf);
//QSslSocket::addDefaultCaCertificate(certs.first());
//loginRequest.setSslConfiguration(sslConf);
QObject::connect(connectionManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(printSslErrors2(QNetworkReply*,QList<QSslError>)));
m_reply = connectionManager->get(loginRequest);
QObject::connect(m_reply, SIGNAL(readyRead()), this, SLOT(getCookie()));
QObject::connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(printSslErrors(QList<QSslError>)));当这段代码执行时,我在WireShark (filter: tcp && ssl && ip.addr == my_addr)中有以下消息:
Client Hello
ServerHello, Certificate
Server Key Exchange, Certificate request, Server Hello Done
Alert (level: Warning, Description: no certificate), client key exchange, change cipher spec, encrypted handshake message
Alert (level: Fatal, Description: Handshake failure)这是意料之中的-应用证书的代码被注释掉了,但奇怪的是-我没有从我的QNetworkAccessManager和QNetworkReply (插槽printSslErrors和printSslErrors2)得到任何ssl错误。
如果我取消注释这3行中的任何一行:
//QSslConfiguration::setDefaultConfiguration(sslConf);
//QSslSocket::addDefaultCaCertificate(certs.first());
//loginRequest.setSslConfiguration(sslConf);我在wireshark中什么也得不到( SYN、ACK和FIN tcp消息很少,但没有http或ssl流量)。此外,QNetworkAccessManager和QNetworkReply仍然没有错误,所以我不知道出了什么问题。
有没有机会让Qt接受我的本地证书,或者可能有一些3d的面向qt的库来帮助我?
附言: btw - ssl和https在几天前工作得很好,在服务器被更改为需要客户端证书之前。
附言:证书是自签名的,如果它有任何不同的话。我还试着把它( p12文件)安装到系统中,Chrome和IE7都可以使用它并与服务器通信。
发布于 2013-12-18 16:39:34
解决方案,第一部分:我基本上解决了这个问题(缺乏连接),原因有两个:
第一- apache服务器实际上需要私钥(不知什么原因,在这里找到),如何添加私钥:
QFile x(Preferences::certificateKeyPath());
x.open(QIODevice::ReadOnly);
pKey = QSslKey(x.readAll(),QSsl::Rsa);
QSslError error1(QSslError::SelfSignedCertificate, certs.first());
QSslError error2(QSslError::CertificateUntrusted, certs.first());
QList<QSslError> expectedSslErrors;
expectedSslErrors.append(error1);
expectedSslErrors.append(error2);2d -我的证书不是很“好”。我不知道它到底是什么意思,也不知道为什么它不工作,但当我从服务器管理员那里获得新证书并添加私钥时,握手成功了。
我仍然不知道如何捕获sslErrors (例如,向用户显示他的证书不工作),但这是一个很好的开始
解决方案,第II部分:
解决了问题的最后一部分(一个问题)。在Qt bug tracker中发现,QNetworkReply不发出SslErrors似乎是一个错误(或者至少它并不总是有效,或者不适用于所有网站)。而解决方法也是从那里: sinse我们不能获得错误,我们必须尝试获得smth SslErrors -例如,错误。它没有给出实际发生了什么的详细信息,但总比什么都没有好。对于我来说,错误代码6-“SSL/TLS握手失败,无法建立加密通道。应该已经发出了sslErrors()信号。”是完美的(我不关心其他任何事情):
QObject::connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleSslErrors(QNetworkReply::NetworkError)));重要的是:如果用户有错误的证书和/或密钥,信号就会发出。但是如果证书和密钥是正确的,它也会被发出。身份验证看起来可能还不够完美,但你可以很容易地用以下命令关闭它
QObject::connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(printSslErrors(QList<QSslError>)));总结似乎他们已经修复了Qt4.8中的许多SSL错误,所以我希望很快就能发布。
发布于 2011-09-22 05:48:54
完全是在黑暗中拍摄的,并假设Qt实际上可能报告了一个错误,但您没有得到信号。
您正在将信号从connectionManager连接到this是否在this的标头中包含了Q_OBJECT宏
还要在运行应用程序时检查输出,因为Qt可能会报告连接信号/插槽的问题,如果确实是这样的话。
https://stackoverflow.com/questions/7506223
复制相似问题