Sur cette page

Serveur et client SSL

Configuration d’un réseau d’objets distants sécurisé à l’aide de QSslSockets.

Le chiffrement des communications est essentiel lorsque vous devez transmettre des données via un réseau sur lequel vous n'avez pas un contrôle total. Les deux applications présentées dans cet exemple montrent comment partager des objets distants via une connexion SSL et comment y accéder.

Terminal exécutant sslserver et affichant l'heure actuelle

sslserver et sslcppclient utilisent tous deux un certificat CA racine personnalisé pour valider leurs certificats respectifs, tous situés dans le répertoire sslserver/cert.

Serveur SSL

Le serveur SSL est configuré avec des certificats et une clé privée.

auto config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem")));
QFile certificateFile(QStringLiteral(":/sslcert/server.crt"));
if (certificateFile.open(QIODevice::ReadOnly | QIODevice::Text))
    config.setLocalCertificate(QSslCertificate(certificateFile.readAll(), QSsl::Pem));
else
    qFatal("Could not open certificate file");
QFile keyFile(QStringLiteral(":/sslcert/server.key"));
if (keyFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
    QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
    if (key.isNull())
        qFatal("Key is not valid");
    config.setPrivateKey(key) ;
} else {
    qFatal("Could not open key file");
}
config.setPeerVerifyMode(QSslSocket::VerifyPeer);
QSslConfiguration::setDefaultConfiguration(config);

Ensuite, il crée un objet ` QRemoteObjectHost ` et un objet ` QSslServer `. L'objet ` QSslServer ` écoute sur le port 65511. Puis, la méthode `setHostUrl` est appelée sur l'objet ` QRemoteObjectHost ` avec l'URL de l'objet ` QSslServer `.

QRemoteObjectHost host;
QSslServer server;
server.listen(QHostAddress::Any, 65511);
host.setHostUrl(server.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);

Un lambda est utilisé pour gérer le signal `errorOccurred` en affichant l’erreur sur le terminal. Un deuxième lambda est connecté au signal `pendingConnectionAvailable`, qui relie un gestionnaire d’erreurs, et appelle la méthode `addHostSideConnection` sur l’objet ` QRemoteObjectHost ` en lui passant le socket entrant en argument afin que l’objet hôte utilise ce socket pour la communication.

QObject::connect(&server, &QSslServer::errorOccurred,
                 [](QSslSocket*socket, QAbstractSocket::SocketErrorerror) {
                     Q_UNUSED(socket);
                     qDebug() << "QSslServer::errorOccurred" << error;
                 });
QObject::connect(&server, &QSslServer::pendingConnectionAvailable, [&server, &host]() {
    qDebug() << "New connection available";
    QSslSocket*socket = qobject_cast<QSslSocket*>(server.nextPendingConnection());
    Q_ASSERT(socket);
    QObject::connect(socket, &QSslSocket::errorOccurred,
                     [](QAbstractSocket::SocketErrorerror) {
                         qDebug() << "QSslSocket::error" << error;
                     });
    host.addHostSideConnection(socket);
});

Enfin, un objet MinuteTimer est créé et la méthode enableRemoting est appelée sur l'objet QRemoteObjectHost avec l'objet MinuteTimer comme argument afin de permettre son partage.

MinuteTimer timer;
host.enableRemoting(&timer);

Client SSL

Le sslcppclient définit le certificat CA racine, puis crée un objet Tester.

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    auto config = QSslConfiguration::defaultConfiguration();
    config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem")));
    QSslConfiguration::setDefaultConfiguration(config);

    Tester t;
    return a.exec();
}

Dans le constructeur de Tester, un objet temporaire de type ` QRemoteObjectNode ` est créé, et la méthode `setupConnection` est utilisée pour créer et configurer un objet ` QSslSocket `. Un gestionnaire d’erreurs est associé, et l’objet ` QSslSocket ` est utilisé par l’objet ` QRemoteObjectNode ` en appelant la méthode `addClientSideConnection` sur celui-ci.

QRemoteObjectNode m_client;
auto socket = setupConnection();
connect(socket, &QSslSocket::errorOccurred,
        socket, [](QAbstractSocket::SocketErrorerror){
    qDebug() << "QSslSocket::error" << error;
}) ;
m_client.addClientSideConnection(socket);

Ensuite, trois objets ` QScopedPointer `, membres de la classe `Tester`, sont connectés à trois répliques de `MinuteTimer` à l’aide de la méthode `acquire` sur l’objet ` QRemoteObjectNode `. Enfin, la méthode ` QTimer::singleShot ` est appelée quatre fois pour déclencher une réinitialisation après un certain délai.

ptr1.reset(m_client.acquire< MinuteTimerReplica >());
ptr2.reset(m_client.acquire< MinuteTimerReplica >());
ptr3.reset(m_client.acquire< MinuteTimerReplica >());
QTimer::singleShot(0, this, &Tester::clear);
QTimer::singleShot(1, this, &Tester::clear);
QTimer::singleShot(10000, this, &Tester::clear);
QTimer::singleShot(11000, this, &Tester::clear);

Lorsque la méthode `Tester::clear` est appelée les trois premières fois, un pointeur est vérifié pour s'assurer qu'il est lié, puis réinitialisé, en choisissant à chaque fois un pointeur différent. Lorsqu'elle est appelée pour la quatrième fois, elle provoque la fermeture de l'application.

void clear()
{
    static int i = 0;
    if (i== 0) {
        i++;
        if (ptr1.isNull())
            qCritical() << "Pointer 1 was not set";
        ptr1.reset();
    } else if (i== 1) {
        i++;
        if (ptr2.isNull())
            qCritical() << "Pointer 2 was not set";
        ptr2.reset();
    } else if (i== 2) {
        i++;
        if (ptr3.isNull())
            qCritical() << "Pointer 3 was not set";
        ptr3.reset();
    } else {
        qApp->quit();
    }
}

Exemple de projet sur code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.