客户端应用如何通过Qt中的自签名证书连接到SSL服务器?

Han*_*ani 2 ssl qt certificate self-signed

我想通过ssl和端口995与我的客户端应用程序的POP3服务器进行通信,服务器证书是自签名的,并且在运行应用程序时收到的错误是:

证书是自签名的,不受信任

代码的一部分是:

socket = new QSslSocket(this);
QFile certfile("D:\\hani\\cert\\localhost.localdomain.pem");
Q_ASSERT(certfile.open(QIODevice::ReadOnly));
QList<QSslCertificate> certList;
QSslCertificate cert(&certfile,QSsl::Pem);
certList.append(cert);
socket->addCaCertificate(cert);
socket->setCaCertificates(certList);
QList<QSslCertificate> serverCert = socket->caCertificates();
Run Code Online (Sandbox Code Playgroud)

我能做什么?

mar*_*o.m 8

不要,让我再说一遍,不要打电话ignoreSslErrors().它完全违背了SSL/TLS的目的.有一些非常特殊的情况可以安全地调用它,但这个(自签名证书)不是特例.

以下可以运行的最小代码显示了如何安全地接受服务器自签名证书.不要捷径.

司机:

int main(int argc, char** argv) {
    QCoreApplication app(argc, argv);
    QTextStream log(stdout);
    DummyClient dummy(log);
    QObject::connect(&dummy, SIGNAL(done()), &app, SLOT(quit()));
    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

DummyClient类:

/*
 * Show how to safely authenticate a TLS server which uses a self-signed certificate.
 * Warning: No error handling to keep the code short.
 */
class DummyClient : public QObject {
    Q_OBJECT
public:
    DummyClient(QTextStream& log)
        : _log(log),
          _sock(new QSslSocket(this)) {
        connect(_sock, SIGNAL(encrypted()), this, SLOT(onEncrypted()));
        connect(_sock, SIGNAL(sslErrors(QList<QSslError>)),
                this, SLOT(onSslErrors(QList<QSslError>)));
        connect(_sock, SIGNAL(error(QAbstractSocket::SocketError)),
                this, SLOT(onErrors(QAbstractSocket::SocketError)));

        // Trust store: which CAs or self-signed certs we are going to trust.
        //
        // We use setCaCertificates() instead than QSslSocket::addCaCertificates()
        // because we don't want to trust the ~200 default CAs.
        QList<QSslCertificate> trustedCas = QSslCertificate::fromPath("server-cert.pem");
        if (trustedCas.empty()) {
            qFatal("Error: no trusted Cas");
        }
        _sock->setCaCertificates(trustedCas);

        bool mutualAuth = false;
        if (mutualAuth) {
            // Our identity
            _sock->setPrivateKey("client-key.pem");
            _sock->setLocalCertificate("client-cert.pem");
        }

        _log << "Connecting" << endl;
        // Note: serverName must match the cert CN or alternative name.
        Qstring serverName = "myserver.example.org";
        _sock->connectToHostEncrypted(serverName, 995);
    }

signals:
    void done();

private slots:
    void onEncrypted() {
        _log << "onEncrypted" << endl;

        /* Everything is good. Start communicating. */

        emit done();
    }

    void onSslErrors(QList<QSslError> errors) {
        QSslError first = errors.takeFirst();
        _log << "onSslErrors: " << first.errorString() << endl;

        /* Something went wrong in the TLS handshake. Inform the user and quit! */

        emit done();
    }

    void onErrors(QAbstractSocket::SocketError) {
        _log << "onErrors: " << _sock->errorString() << endl;
        emit done();
    }

private:
    QTextStream& _log;
    QSslSocket* _sock;
};
Run Code Online (Sandbox Code Playgroud)