使用QT为SSL制作自定义根证书存储区的问题?

时间:2011-01-28 18:29:02

标签: qtwebkit qtnetwork

我正在使用QWebView和Qt在Qt中开发自定义浏览器 我正在尝试创建自己的受信任证书的根证书存储库,这些证书来自mozilla项目。

我使用QSslSocket :: setDefaultCaCertificates()来覆盖默认证书。 但是我无法加载https://www.gmail.com,就像在mozilla中一样。

我已将gmail的所有必需的根证书设置到我的商店。

任何人都可以指导我吗?

1 个答案:

答案 0 :(得分:4)

您无法连接的原因是因为当您连接到www.gmail.com时向您呈现的SSL证书(带有序列2F:DF:BC:F6:AE:91:52:6D:0F:9A:A3:DF:40:34:3E:9A)是针对其他域发布的 - www.google.com。这与根CA证书存储无关,因为不需要根CA证书来将证书的Subject CN字段与您尝试连接的主机进行比较。您可以通过调用
来忽略此错误和其他SSL错误 void QNetworkReply::ignoreSslErrors () [virtual slot]
为避免此错误,您可以直接连接到https://mail.google.com,当您尝试连接到https://www.gmail.com

时,这是您要重定向到的域

下面是一个工作示例,它将向您显示确切的SSL错误和QNAM级别错误。线B1或线B2必须同时有效。如果要查看默认(系统)根CA证书存储区发生的情况,可以对A行进行注释。此代码使用了两个证书;具有序列30:00:00:02的CA证书应放在名为ThawteSGCCA.crt的文件中,并且带有序列70:BA:E4:1D:10:D9:29:34:B6:38:CA:7B:03:CC:BA:BF的CA证书应放在名为BuiltinObjectToken-VerisignClass3PublicPrimaryCertificationAuthority.crt的文件中。

#include <QtGui/QApplication>
#include <QtCore/QDebug>
#include <QtCore/QList>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QSslConfiguration>
#include <QtNetwork/QSslSocket>
#include <QtNetwork/QSslError>
#include <QtWebKit/QWebFrame>
#include <QtWebKit/QWebPage>



class Handler : public QObject{
    Q_OBJECT

public slots:

    void slotLoadFinished(bool ok) {
        if (ok) {
            qDebug() << "Page size: " << static_cast<QWebPage*>(sender())->mainFrame()->toHtml().size();
        }
    }

    void slotFinished(QNetworkReply * reply) {
        if (reply->error() == QNetworkReply::NoError) {
            qDebug() << "connected to " << reply->url();
            qDebug() << "HTTP status: " << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

        } else {
            qDebug() << "error while connecting to " << reply->url();
            qDebug() << "error code: " << reply->error();
            qDebug() << "error string: " << reply->errorString();
        }
    }

    void slotSslErrors(QNetworkReply * reply, QList<QSslError> const & errors) {
        qDebug() << "SSL errors: " << errors;
        qDebug() << "peer's certificate: "
                 << reply->sslConfiguration().peerCertificate();
    }

};


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Handler handler;

    // CA certs for:
    // 1. cert with Subject.CN == mail.google.com cert with serial 1f:19:f6:de:35:dd:63:a1:42:91:8a:d5:2c:c0:ab:12
    // 2. cert with Subject.CN == www.google.com cert with serial 2F:DF:BC:F6:AE:91:52:6D:0F:9A:A3:DF:40:34:3E:9A
    QList<QSslCertificate> CAcerts =
            // serial 30:00:00:02
            QSslCertificate::fromPath("ThawteSGCCA.crt") +
            // serial 70:BA:E4:1D:10:D9:29:34:B6:38:CA:7B:03:CC:BA:BF
            QSslCertificate::fromPath("BuiltinObjectToken-VerisignClass3PublicPrimaryCertificationAuthority.crt");

    qDebug() << "root CA certificates:\n"
             << CAcerts
             << "\n";
    QSslSocket::setDefaultCaCertificates(CAcerts); // line A

    QWebPage page;
    // OK because cert with serial 1f:19:f6:de:35:dd:63:a1:42:91:8a:d5:2c:c0:ab:12 is for host mail.google.com
//  page.mainFrame()->load(QUrl("https://mail.google.com")); // line B1
    // SSL ERROR "The host name did not match any of the valid hosts for this certificate"
    // because cert with serial 1f:19:f6:de:35:dd:63:a1:42:91:8a:d5:2c:c0:ab:12 is NOT for www.gmail.com
    page.mainFrame()->load(QUrl("https://www.gmail.com")); // line B2

    QObject::connect(page.networkAccessManager(), SIGNAL(finished(QNetworkReply*)), &handler, SLOT(slotFinished(QNetworkReply*)));
    QObject::connect(page.networkAccessManager(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), &handler, SLOT(slotSslErrors(QNetworkReply*,QList<QSslError>)));
    QObject::connect(&page, SIGNAL(loadFinished(bool)), &handler, SLOT(slotLoadFinished(bool)));

    return app.exec();
}

#include "main.moc"