Cliente CoAP de seguridad rápida
Asegurar el cliente CoAP y utilizarlo con una interfaz de usuario Qt Quick.

Quick Secure CoAP Client muestra cómo crear un cliente CoAP seguro y utilizarlo en una aplicación Qt Quick.
Nota: Qt CoAP no proporciona una API QML en su versión actual. Sin embargo, puedes hacer que las clases C++ del módulo estén disponibles para QML como se muestra en el ejemplo.
Ejecución del ejemplo
Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para obtener más información, consulte Qt Creator: Tutorial: Construir y ejecutar.
Para ejecutar la aplicación de ejemplo, primero debe configurar un servidor CoAP seguro. Puede ejecutar el ejemplo con cualquier servidor CoAP seguro que admita uno de los modos de autenticación de clave precompartida (PSK) o de certificado. Para obtener más información sobre la configuración de un servidor CoAP seguro, consulte Configuración de un servidor CoAP seguro.
Exposición de clases C++ a QML
En este ejemplo, debe exponer la clase QCoapClient y el espacio de nombres QtCoap a QML. Para ello, cree una clase envoltorio personalizada y utilice las macros de registro especiales.
Cree la clase QmlCoapSecureClient como una envoltura alrededor de QCoapClient. Esta clase también contiene el modo de seguridad seleccionado y los parámetros de configuración de seguridad. Utilice la macro Q_INVOKABLE para exponer varios métodos a QML. Utilice también la macro QML_NAMED_ELEMENT para registrar la clase en QML como 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; };
Después de eso, registra el espacio de nombres QtCoap, para que puedas utilizar los enums proporcionados allí:
namespace QCoapForeignNamespace { Q_NAMESPACE QML_FOREIGN_NAMESPACE(QtCoap) QML_NAMED_ELEMENT(QtCoap) }
Ajuste de los archivos de compilación
Para que los tipos personalizados estén disponibles desde QML, actualice los archivos del sistema de compilación en consecuencia.
CMake
Para una compilación basada en CMake, añada lo siguiente a CMakeLists.txt:
qt_add_qml_module(quicksecureclient
URI CoapSecureClientModule
SOURCES
qmlcoapsecureclient.cpp qmlcoapsecureclient.h
QML_FILES
FilePicker.qml
Main.qml
)qmake
Para una compilación basada en qmake, modifique el archivo quicksecureclient.pro de la siguiente manera:
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_resourcesUso de nuevos tipos QML
Ahora, cuando las clases C++ estén correctamente expuestas a QML, podrás utilizar los nuevos tipos.
Creación del cliente
CoapSecureClient es instanciado desde el archivo Main.qml. Maneja la señal QmlCoapSecureClient::finished() y actualiza la UI en consecuencia:
CoapSecureClient { id: client onFinished: (result) => { outputView.text = result; statusLabel.text = ""; disconnectButton.enabled = true; } }
La instancia de QCoapClient se crea cuando el usuario selecciona o cambia el modo de seguridad en la UI. El método QmlCoapSecureClient::setSecurityMode() se invoca desde el código QML cuando se selecciona uno de los modos de seguridad:
ButtonGroup { id: securityModeGroup onClicked: { if ((securityModeGroup.checkedButton as RadioButton) === preSharedMode) client.setSecurityMode(QtCoap.SecurityMode.PreSharedKey); else client.setSecurityMode(QtCoap.SecurityMode.Certificate); } }
En el lado C++, este método crea un QCoapClient y se conecta a sus señales finished() y error(). La clase gestiona internamente ambas señales y las reenvía a la nueva señal 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)); }); } }
Envío de una solicitud
Pulsa el botón Send Request para establecer la configuración de seguridad basada en el modo de seguridad seleccionado y enviar una solicitud 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); } }
Existen dos sobrecargas para el método setSecurityConfiguration.
La sobrecarga para el modo PSK simplemente establece la identidad del cliente y la clave precompartida:
void QmlCoapSecureClient::setSecurityConfiguration(const QString &preSharedKey, const QString &identity) { QCoapSecurityConfiguration configuration; configuration.setPreSharedKey(preSharedKey.toUtf8()); configuration.setPreSharedKeyIdentity(identity.toUtf8()); m_configuration = configuration; }
Y la sobrecarga para certificados X.509 lee los archivos de certificado y la clave privada y establece la configuración de seguridad:
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; }
Tras establecer la configuración de seguridad, el método sendGetRequest establece la URL de solicitud y envía una solicitud a 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); }
Al enviar la primera solicitud, se realiza un "handshake" con el servidor CoAP. Una vez que el handshake se ha realizado con éxito, todos los mensajes subsiguientes están encriptados, y cambiar la configuración de seguridad después de un handshake exitoso no tendrá ningún efecto. Si quieres cambiarla, o cambiar el host, necesitas desconectarte primero.
void QmlCoapSecureClient::disconnect() { if (m_coapClient) m_coapClient->disconnect(); }
Esto abortará el handshake y cerrará los sockets abiertos.
Para la autenticación mediante certificados X.509, es necesario especificar los archivos de certificado. Para ello se utiliza el componente FilePicker. Combina un campo de texto y un botón para abrir un diálogo de archivo cuando se pulsa el botón:
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 se instancia varias veces en el archivo Main.qml para crear campos de entrada para los certificados y la clave privada:
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 }
Configuración de un servidor CoAP seguro
Para ejecutar este ejemplo, es necesario disponer de un servidor CoAP seguro que admita los modos PSK o Certificado (o ambos). Tiene las siguientes opciones:
- Construir y ejecutar manualmente un servidor CoAP seguro utilizando, por ejemplo, libcoap, Californium, FreeCoAP, o cualquier otra librería CoAP que soporte DTLS.
- Utilizar las imágenes Docker listas disponibles en Docker Hub, que construyen y ejecutan los servidores CoAP seguros adecuados para nuestro ejemplo. A continuación se describen los pasos necesarios para utilizar los servidores CoAP basados en Docker.
Configuración de un servidor para el modo PSK
El siguiente comando extrae el contenedor docker para un servidor CoAP seguro basado en Californium plugtest (que no es seguro por defecto) del Docker Hub y lo inicia:
docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp tqtc/coap-californium-test-server:3.8.0
El servidor CoAP de prueba será accesible en los puertos 5683 (no seguro) y 5684 (seguro). Para obtener instrucciones sobre cómo recuperar la dirección IP, consulte Obtener la dirección IP.
Para ejecutar el ejemplo con este servidor, debe establecer la clave precompartida en secretPSK y la identidad en Client_identity.
Configuración de un servidor para el modo certificado
La imagen docker del servidor seguro que utiliza autenticación con certificados X.509 está basada en el ejemplo del servidor de tiempo de la librería FreeCoAP. El siguiente comando extrae el contenedor de Docker Hub y lo inicia:
docker run --name coap-time-server -d --rm -p 5684:5684/udp tqtc/coap-secure-time-server:freecoap
Para obtener instrucciones sobre cómo recuperar la dirección IP, consulta Obtener la dirección IP. El servidor de prueba CoAP será accesible por la dirección IP recuperada en el puerto 584 y la ruta de recursos /time.
Para ejecutar el ejemplo con este servidor, es necesario especificar los archivos de certificado requeridos por el servidor. Se encuentran en el contenedor docker, en el directorio /root/certs. Para copiarlos a un directorio local, utilice el siguiente comando:
docker cp <container_id>:/root/certs <local_directory_path>
Por ejemplo:
$ docker cp 5e46502df88f:/root/certs ~/
Las instrucciones para obtener el ID del contenedor se describen a continuación.
Obtener la dirección IP
Para averiguar la dirección IP de un contenedor docker, primero obtenga el ID del contenedor ejecutando el comando docker ps, que mostrará algo como:
$ docker ps CONTAINER ID IMAGE 5e46502df88f tqtc/coap-californium-test-server:3.8.0
A continuación, puede obtener la dirección IP con el siguiente comando:
docker inspect <container_id> | grep IPAddress
Por ejemplo:
$ docker inspect 5e46502df88f | grep IPAddress ... "IPAddress": "172.17.0.2", ...
Terminar un contenedor Docker
Para terminar un contenedor Docker después de su uso, utilice el siguiente comando:
docker stop <container_id>
El <container_id> aquí es el mismo que el recuperado por el comando docker ps.
Archivos:
© 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.