ThingsBoard文档

ThingsBoard平台使用文档。

X.509凭据认证

X.509基于证书的身份验证用于双向SSL连接。在这种情况下证书本身就是客户端的ID,因此不再需要访问令牌。

以下说明将描述如何生成客户端证书以及如何通过SSL连接到运行MQTT的服务器。你将需要具有PEM格式的服务器证书的公钥。有关服务器端配置的更多详细信息请参见以下说明。

更新keygen.properties文件

打 keygen.properties文件并根据需要更新对应内容:

DOMAIN_SUFFIX="$(hostname)"
ORGANIZATIONAL_UNIT=ThingsBoard
ORGANIZATION=ThingsBoard
CITY=San Francisco
STATE_OR_PROVINCE=CA
TWO_LETTER_COUNTRY_CODE=US

SERVER_KEYSTORE_PASSWORD=server_ks_password
SERVER_KEY_PASSWORD=server_key_password

SERVER_KEY_ALIAS="serveralias"
SERVER_FILE_PREFIX="mqttserver"
SERVER_KEYSTORE_DIR="/etc/thingsboard/conf/"

CLIENT_KEYSTORE_PASSWORD=password
CLIENT_KEY_PASSWORD=password

CLIENT_KEY_ALIAS="clientalias"
CLIENT_FILE_PREFIX="mqttclient"

运行客户端密钥生成脚本

下载并启动client.keygen.sh脚本。

chmod +x client.keygen.sh
./client.keygen.sh

该脚本输出以下文件:

  • CLIENT_FILE_PREFIX.jks - 导入了服务器证书的Java密钥库文件
  • CLIENT_FILE_PREFIX.nopass.pem - 非Java客户端使用的PEM格式的客户端证书文件
  • CLIENT_FILE_PREFIX.pub.pem - 客户端公共钥

将客户端公钥设置为设备凭据

ThingsBoard Web UI -> Devices -> Your Device -> Device Credentials. 选择X.509凭据, 插入CLIENT_FILE_PREFIX.pub.pem 文件内容并保存或者通过REST API进行相同操作。

运行双向MQTT SSL Python客户端

下载Python客户端示例two-way-ssl-mqtt-client.py。 指定你的客户端证书和服务器证书公钥的路径。

# Some code omitted

client.tls_set(ca_certs="mqttserver.pub.pem", certfile="mqttclient.nopass.pem", keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
                       tls_version=ssl.PROTOCOL_TLSv1, ciphers=None);

# Some code omitted

注意 脚本使用 8883 mqtt端口和需要paho mqtt库你可以使用以下命令进行安装:pip install paho-mqtt

运行脚本:

如果一切配置正确,则输出应为:

resources/mqtt-ssl-configuration-twowaysslmqttclient-output.txt
Connected with result code 0
Topic: v1/devices/me/attributes/response/1
Message: {}

To run Java client, import CLIENT_FILE_PREFIX.jks file as follows:

resources/MqttSslClient.java
import com.google.common.io.Resources;
import org.eclipse.paho.client.mqttv3.*;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;

public class MqttSslClient {

    private static final String MQTT_URL = "ssl://localhost:8883";

    private static final String clientId = "MQTT_SSL_JAVA_CLIENT";
    private static final String keyStoreFile = "mqttclient.jks";
    private static final String JKS="JKS";
    private static final String TLS="TLS";
    private static final String CLIENT_KEYSTORE_PASSWORD = "password";
    private static final String CLIENT_KEY_PASSWORD = "password";

    public static void main(String[] args) {

        try {

            URL ksUrl = Resources.getResource(keyStoreFile);
            File ksFile = new File(ksUrl.toURI());
            URL tsUrl = Resources.getResource(keyStoreFile);
            File tsFile = new File(tsUrl.toURI());

            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            KeyStore trustStore = KeyStore.getInstance(JKS);
            trustStore.load(new FileInputStream(tsFile), CLIENT_KEYSTORE_PASSWORD.toCharArray());
            tmf.init(trustStore);
            KeyStore ks = KeyStore.getInstance(JKS);

            ks.load(new FileInputStream(ksFile), CLIENT_KEYSTORE_PASSWORD.toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, CLIENT_KEY_PASSWORD.toCharArray());

            KeyManager[] km = kmf.getKeyManagers();
            TrustManager[] tm = tmf.getTrustManagers();
            SSLContext sslContext = SSLContext.getInstance(TLS);
            sslContext.init(km, tm, null);

            MqttConnectOptions options = new MqttConnectOptions();
            options.setSocketFactory(sslContext.getSocketFactory());
            MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId);
            client.connect(options);
            Thread.sleep(3000);
            MqttMessage message = new MqttMessage();
            message.setPayload("{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4}".getBytes());
            client.publish("v1/devices/me/telemetry", message);
            client.disconnect();
            System.out.println("Disconnected");
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}