2

我需要与需要本地证书(.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 中有以下消息(过滤器: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 库来帮助我?

PS:顺便说一句 - ssl 和 https 几天前工作得很好,在服务器被更改为需要客户端证书之前。

PPS:如果有任何区别,证书是自签名的。我还尝试将它(p12 文件)“安装”到系统中,Chrome 和 IE7 都可以使用它并与服务器通信。

4

2 回答 2

1

在黑暗中完成拍摄并假设 Qt 实际上可能正在报告错误但您没有收到信号。

您正在连接来自您的信号,connectionManager以便在标题中this包含宏?Q_OBJECTthis

运行应用程序时还要检查输出,因为如果此处确实是这种情况,Qt 可能会报告连接信号/插槽的问题。

于 2011-09-21T21:48:53.953 回答
0

解决方案,第一部分: 我主要解决了这个问题(缺乏连接),有两个原因:

1st - apache 服务器实际上需要私钥(出于某种未知原因,在 [here][1] 找到它),如何添加私钥:

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(例如向用户显示他的证书不起作用),但这是一个好的开始

解决方案,第二部分:

解决了问题的最后一部分(kina a woraround)。似乎 QNetworkReply 没有发出 SslErrors 是一个错误(或者至少它不是一直有效或不适用于所有网站),在 [Qt bug tracker][2] 中发现了它。解决方法也从那里开始:我们无法获得 SslErrors,我们必须尝试获得其他东西 - 例如,[错误] [3]。它没有提供有关实际发生的事情的详细信息,但总比没有好。对我来说,错误代码 6 -“SSL/TLS 握手失败,无法建立加密通道。应该发出 sslErrors() 信号。” 是完美的(我不关心其他任何事情):

 QObject::connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleSslErrors(QNetworkReply::NetworkError)));

重要的部分:如果用户有错误的证书和/或密钥 - 发出信号。但如果证书和密钥正确,也会发出它。似乎 auth 可能仍然不完美,但你可以很容易地关闭它

QObject::connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), 
                  this, SLOT(printSslErrors(QList<QSslError>)));

结论似乎他们在 Qt 4.8 中修复了很多 SSL 错误,所以我希望尽快发布

于 2013-12-18T08:39:34.373 回答