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からsslエラーが発生しません(スロットprintSslErrorsとprintSslErrors2)。

これらの3行のいずれかをコメント解除した場合:

 //QSslConfiguration::setDefaultConfiguration(sslConf);
 //QSslSocket::addDefaultCaCertificate(certs.first());
 //loginRequest.setSslConfiguration(sslConf);

Wiresharkでは何も表示されません(SYN、ACK、およびFINのtcpメッセージはほとんどありませんが、httpまたはsslトラフィックはありません)。また、QNetworkAccessManagerとQNetworkReplyからのエラーはまだないので、何が問題になっているのかはわかりません。

Qtに私のローカル証明書を受け入れさせる機会はありますか、それとも私を助けるためのサードパーティの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

解決策、パートI: 私は主にこれを解決しました(接続の欠如)、2つの理由がありました:

1番目-Apacheサーバーは実際に秘密鍵を必要とします(何らかの理由で、[ここ] [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をキャッチする方法(たとえば、証明書が機能していないことをユーザーに表示する方法)はまだわかりませんが、良いスタートです。

ソリューション、パートII:

質問の最後の部分を解決しました(ちょっとワララウンド)。QNetworkReplyがSslErrorsを発行しないのはバグのようです(または少なくとも、常にまたはすべてのWebサイトで機能するわけではありません)。[Qtバグトラッカーで][2]発見しました。そして、そこからの回避策もあります。SslErrorsを取得できないため、他の方法でsmthを取得する必要があります-[エラー][3]など。それは実際に何が起こったのかについての詳細な情報を提供しませんが、何もないよりはましです。私の場合、エラーコード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バグが修正されたようですので、まもなくリリースされることを願っています

于 2013-12-18T08:39:34.373 に答える