首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有ssl本地证书的QNetworkRequest

具有ssl本地证书的QNetworkRequest
EN

Stack Overflow用户
提问于 2011-09-22 04:29:46
回答 2查看 5.9K关注 0票数 2

我需要与需要本地证书(.crt文件)的服务器交换数据。我试试这个:

代码语言:javascript
复制
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)中有以下消息:

代码语言:javascript
复制
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行中的任何一行:

代码语言:javascript
复制
 //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都可以使用它并与服务器通信。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-18 16:39:34

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

第一- apache服务器实际上需要私钥(不知什么原因,在这里找到),如何添加私钥:

代码语言:javascript
复制
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()信号。”是完美的(我不关心其他任何事情):

代码语言:javascript
复制
 QObject::connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleSslErrors(QNetworkReply::NetworkError)));

重要的是:如果用户有错误的证书和/或密钥,信号就会发出。但是如果证书和密钥是正确的,它也会被发出。身份验证看起来可能还不够完美,但你可以很容易地用以下命令关闭它

代码语言:javascript
复制
QObject::connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), 
                  this, SLOT(printSslErrors(QList<QSslError>)));

总结似乎他们已经修复了Qt4.8中的许多SSL错误,所以我希望很快就能发布。

票数 0
EN

Stack Overflow用户

发布于 2011-09-22 05:48:54

完全是在黑暗中拍摄的,并假设Qt实际上可能报告了一个错误,但您没有得到信号。

您正在将信号从connectionManager连接到this是否在this的标头中包含了Q_OBJECT

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7506223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档