Quick Secure CoAP Client
Sécuriser le client CoAP et l'utiliser avec une interface utilisateur Qt Quick.

Quick Secure CoAP Client montre comment créer un client CoAP sécurisé et l'utiliser dans une application Qt Quick.
Remarque : Qt CoAP ne fournit pas d'API QML dans sa version actuelle. Cependant, vous pouvez rendre les classes C++ du module disponibles pour QML comme cela est montré dans l'exemple.
Exécution de l'exemple
Pour exécuter l'exemple à partir de Qt Creatorouvrez le mode Welcome et sélectionnez l'exemple à partir de Examples. Pour plus d'informations, voir Qt Creator: Tutoriel : Construire et exécuter.
Pour exécuter l'application d'exemple, vous devez d'abord configurer un serveur CoAP sécurisé. Vous pouvez exécuter l'exemple avec n'importe quel serveur CoAP sécurisé prenant en charge l'un des modes d'authentification par clé pré-partagée (PSK ) ou par certificat. Pour plus d'informations sur la configuration d'un serveur CoAP sécurisé, voir Configuration d'un serveur CoAP sécurisé.
Exposition de classes C++ à QML
Dans cet exemple, vous devez exposer la classe QCoapClient et l'espace de noms QtCoap à QML. Pour ce faire, créez une classe enveloppante personnalisée et utilisez les macros d'enregistrement spéciales.
Créez la classe QmlCoapSecureClient en tant que classe enveloppante autour de QCoapClient. Cette classe contient également le mode de sécurité sélectionné et les paramètres de configuration de la sécurité. Utilisez la macro Q_INVOKABLE pour exposer plusieurs méthodes à QML. Utilisez également la macro QML_NAMED_ELEMENT pour enregistrer la classe dans QML en tant que CoapSecureClient.
class QmlCoapSecureClient : public QObject { Q_OBJECT QML_NAMED_ELEMENT(CoapSecureClient) public: QmlCoapSecureClient(QObject *parent = nullptr); ~QmlCoapSecureClient() override; Q_INVOKABLE void setSecurityMode(QtCoap::SecurityMode mode); Q_INVOKABLE void sendGetRequest(const QString &host, const QString &path, int port); Q_INVOKABLE void setSecurityConfiguration(const QString &preSharedKey, const QString &identity); Q_INVOKABLE void setSecurityConfiguration(const QString &localCertificatePath, const QString &caCertificatePath, const QString &privateKeyPath); Q_INVOKABLE void disconnect(); Q_SIGNALS: void finished(const QString &result); private: QCoapClient *m_coapClient; QCoapSecurityConfiguration m_configuration; QtCoap::SecurityMode m_securityMode; };
Ensuite, enregistrez l'espace de noms QtCoap, afin de pouvoir utiliser les enums qui y sont fournis :
namespace QCoapForeignNamespace { Q_NAMESPACE QML_FOREIGN_NAMESPACE(QtCoap) QML_NAMED_ELEMENT(QtCoap) }
Ajustement des fichiers de construction
Pour rendre les types personnalisés disponibles à partir de QML, mettez à jour les fichiers du système de construction en conséquence.
CMake
Pour une compilation basée sur CMake, ajoutez les éléments suivants au fichier CMakeLists.txt:
qt_add_qml_module(quicksecureclient
URI CoapSecureClientModule
SOURCES
qmlcoapsecureclient.cpp qmlcoapsecureclient.h
QML_FILES
FilePicker.qml
Main.qml
)qmake
Pour une compilation basée sur qmake, modifiez le fichier quicksecureclient.pro de la manière suivante :
CONFIG += qmltypes
QML_IMPORT_NAME = CoapSecureClientModule
QML_IMPORT_MAJOR_VERSION = 1
...
qml_resources.files = \
qmldir \
FilePicker.qml \
Main.qml
qml_resources.prefix = /qt/qml/CoapSecureClientModule
RESOURCES += qml_resourcesUtilisation des nouveaux types QML
Maintenant que les classes C++ sont correctement exposées à QML, vous pouvez utiliser les nouveaux types.
Création du client
CoapSecureClient Le client est instancié à partir du fichier Main.qml. Il gère le signal QmlCoapSecureClient::finished() et met à jour l'interface utilisateur en conséquence :
CoapSecureClient { id: client onFinished: (result) => { outputView.text = result; statusLabel.text = ""; disconnectButton.enabled = true; } }
L'instance de QCoapClient est créée lorsque l'utilisateur sélectionne ou modifie le mode de sécurité dans l'interface utilisateur. La méthode QmlCoapSecureClient::setSecurityMode() est invoquée à partir du code QML lorsque l'un des modes de sécurité est sélectionné :
ButtonGroup { id: securityModeGroup onClicked: { if ((securityModeGroup.checkedButton as RadioButton) === preSharedMode) client.setSecurityMode(QtCoap.SecurityMode.PreSharedKey); else client.setSecurityMode(QtCoap.SecurityMode.Certificate); } }
Du côté C++, cette méthode crée un QCoapClient et se connecte à ses signaux finished() et error(). La classe gère les deux signaux en interne et les transmet au nouveau signal finished().
void QmlCoapSecureClient::setSecurityMode(QtCoap::SecurityMode mode) { // Create a new client, if the security mode has changed if (m_coapClient && mode != m_securityMode) { delete m_coapClient; m_coapClient = nullptr; } if (!m_coapClient) { m_coapClient = new QCoapClient(mode); m_securityMode = mode; connect(m_coapClient, &QCoapClient::finished, this, [this](QCoapReply *reply) { if (!reply) emit finished(tr("Something went wrong, received a null reply")); else if (reply->errorReceived() != QtCoap::Error::Ok) emit finished(errorMessage(reply->errorReceived())); else emit finished(reply->message().payload()); }); connect(m_coapClient, &QCoapClient::error, this, [this](QCoapReply *, QtCoap::Error errorCode) { emit finished(errorMessage(errorCode)); }); } }
Envoi d'une requête
Cliquez sur le bouton Send Request pour définir la configuration de sécurité en fonction du mode de sécurité sélectionné et envoyer une requête GET:
Button { id: requestButton text: qsTr("Send Request") enabled: securityModeGroup.checkState !== Qt.Unchecked onClicked: { outputView.text = ""; if ((securityModeGroup.checkedButton as RadioButton) === preSharedMode) client.setSecurityConfiguration(pskField.text, identityField.text); else client.setSecurityConfiguration(localCertificatePicker.selectedFile, caCertificatePicker.selectedFile, privateKeyPicker.selectedFile); client.sendGetRequest(hostComboBox.editText, resourceField.text, parseInt(portField.text)); statusLabel.text = qsTr("Sending request to %1%2...").arg(hostComboBox.editText) .arg(resourceField.text); } }
Il existe deux surcharges pour la méthode setSecurityConfiguration.
La surcharge pour le mode PSK définit simplement l'identité du client et la clé pré-partagée :
void QmlCoapSecureClient::setSecurityConfiguration(const QString &preSharedKey, const QString &identity) { QCoapSecurityConfiguration configuration; configuration.setPreSharedKey(preSharedKey.toUtf8()); configuration.setPreSharedKeyIdentity(identity.toUtf8()); m_configuration = configuration; }
La surcharge pour les certificats X.509 lit les fichiers de certificat et la clé privée et définit la configuration de sécurité :
void QmlCoapSecureClient::setSecurityConfiguration(const QString &localCertificatePath, const QString &caCertificatePath, const QString &privateKeyPath) { QCoapSecurityConfiguration configuration; const auto localCerts = QSslCertificate::fromPath(QUrl(localCertificatePath).toLocalFile(), QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); if (localCerts.isEmpty()) qCWarning(lcCoapClient, "The specified local certificate file is not valid."); else configuration.setLocalCertificateChain(localCerts.toVector()); const auto caCerts = QSslCertificate::fromPath(QUrl(caCertificatePath).toLocalFile(), QSsl::Pem, QSslCertificate::PatternSyntax::FixedString); if (caCerts.isEmpty()) qCWarning(lcCoapClient, "The specified CA certificate file is not valid."); else configuration.setCaCertificates(caCerts.toVector()); QFile privateKey(QUrl(privateKeyPath).toLocalFile()); if (privateKey.open(QIODevice::ReadOnly)) { QCoapPrivateKey key(privateKey.readAll(), QSsl::Ec); configuration.setPrivateKey(key); } else { qCWarning(lcCoapClient) << "Unable to read the specified private key file" << privateKeyPath; } m_configuration = configuration; }
Après avoir défini la configuration de sécurité, la méthode sendGetRequest définit l'URL de la demande et envoie une demande GET:
void QmlCoapSecureClient::sendGetRequest(const QString &host, const QString &path, int port) { if (!m_coapClient) return; m_coapClient->setSecurityConfiguration(m_configuration); QUrl url; url.setHost(host); url.setPath(path); url.setPort(port); m_coapClient->get(url); }
Lors de l'envoi de la première requête, un échange avec le serveur CoAP est effectué. Une fois la poignée de main réussie, tous les messages suivants sont cryptés, et la modification de la configuration de sécurité après une poignée de main réussie n'aura aucun effet. Si vous souhaitez la modifier ou changer d'hôte, vous devez d'abord vous déconnecter.
void QmlCoapSecureClient::disconnect() { if (m_coapClient) m_coapClient->disconnect(); }
Cela annulera la poignée de main et fermera les sockets ouvertes.
Pour l'authentification à l'aide de certificats X.509, les fichiers de certificats doivent être spécifiés. Le composant FilePicker est utilisé à cette fin. Il combine un champ de texte et un bouton pour ouvrir une boîte de dialogue de fichier lorsque le bouton est enfoncé :
Item { id: filePicker property string dialogText property alias selectedFile: filePathField.text height: addFileButton.height FileDialog { id: fileDialog title: qsTr("Please Choose %1").arg(filePicker.dialogText) currentFolder: StandardPaths.writableLocation(StandardPaths.HomeLocation) fileMode: FileDialog.OpenFile onAccepted: filePathField.text = fileDialog.selectedFile } RowLayout { anchors.fill: parent TextField { id: filePathField placeholderText: qsTr("<%1>").arg(filePicker.dialogText) inputMethodHints: Qt.ImhUrlCharactersOnly selectByMouse: true Layout.fillWidth: true } Button { id: addFileButton text: qsTr("Add %1").arg(filePicker.dialogText) onClicked: fileDialog.open() } } }
FilePicker est instancié plusieurs fois dans le fichier Main.qml pour créer des champs de saisie pour les certificats et la clé privée :
FilePicker { id: localCertificatePicker dialogText: qsTr("Local Certificate") enabled: (securityModeGroup.checkedButton as RadioButton) === certificateMode Layout.columnSpan: 2 Layout.fillWidth: true } FilePicker { id: caCertificatePicker dialogText: qsTr("CA Certificate") enabled: (securityModeGroup.checkedButton as RadioButton) === certificateMode Layout.columnSpan: 2 Layout.fillWidth: true } FilePicker { id: privateKeyPicker dialogText: qsTr("Private Key") enabled: (securityModeGroup.checkedButton as RadioButton) === certificateMode Layout.columnSpan: 2 Layout.fillWidth: true }
Mise en place d'un serveur CoAP sécurisé
Pour exécuter cet exemple, vous devez disposer d'un serveur CoAP sécurisé prenant en charge les modes PSK ou Certificat (ou les deux). Vous avez les options suivantes :
- Construire et exécuter manuellement un serveur CoAP sécurisé en utilisant, par exemple, libcoap, Californium, FreeCoAP, ou toute autre bibliothèque CoAP qui supporte DTLS.
- Utiliser les images Docker prêtes à l'emploi disponibles sur Docker Hub, qui construisent et exécutent les serveurs CoAP sécurisés adaptés à notre exemple. Les étapes nécessaires à l'utilisation des serveurs CoAP basés sur Docker sont décrites ci-dessous.
Configuration d'un serveur pour le mode PSK
La commande suivante extrait du Docker Hub le conteneur docker d'un serveur CoAP sécurisé basé sur Californium plugtest (qui n'est pas sécurisé par défaut) et le démarre :
docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp tqtc/coap-californium-test-server:3.8.0
Le serveur CoAP test sera accessible sur les ports 5683 (non sécurisé) et 5684 (sécurisé). Pour obtenir des instructions sur la récupération de l'adresse IP, voir Obtenir l'adresse IP.
Pour exécuter l'exemple avec ce serveur, vous devez définir la clé pré-partagée sur secretPSK et l'identité sur Client_identity.
Configuration d'un serveur en mode certificat
L'image docker du serveur sécurisé utilisant l'authentification avec des certificats X.509 est basée sur l'exemple du serveur de temps de la bibliothèque FreeCoAP. La commande suivante extrait le conteneur de Docker Hub et le démarre :
docker run --name coap-time-server -d --rm -p 5684:5684/udp tqtc/coap-secure-time-server:freecoap
Pour obtenir des instructions sur la récupération de l'adresse IP, voir Obtenir l'adresse IP. Le serveur de test CoAP sera accessible par l'adresse IP récupérée sur le port 5684 et le chemin de ressource /time.
Pour exécuter l'exemple avec ce serveur, vous devez spécifier les fichiers de certificats requis par le serveur. Ils se trouvent dans le conteneur docker, dans le répertoire /root/certs. Pour les copier dans un répertoire local, utilisez la commande suivante :
docker cp <container_id>:/root/certs <local_directory_path>
Par exemple :
$ docker cp 5e46502df88f:/root/certs ~/
Les instructions pour obtenir l'ID du conteneur sont décrites ci-dessous.
Obtenir l'adresse IP
Pour obtenir l'adresse IP d'un conteneur Docker, commencez par récupérer l'ID du conteneur en exécutant la commande docker ps, qui produira quelque chose comme :
$ docker ps CONTAINER ID IMAGE 5e46502df88f tqtc/coap-californium-test-server:3.8.0
Vous pouvez ensuite obtenir l'adresse IP à l'aide de la commande suivante :
docker inspect <container_id> | grep IPAddress
Par exemple :
$ docker inspect 5e46502df88f | grep IPAddress ... "IPAddress": "172.17.0.2", ...
Terminer un conteneur Docker
Pour mettre fin à un conteneur Docker après utilisation, utilisez la commande suivante :
docker stop <container_id>
L'adresse <container_id> est la même que celle récupérée par la commande docker ps.
Fichiers :
© 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.