# ThingsBoard MQTT 认证机制说明 ## 概述 ThingsBoard 支持两种 MQTT 认证方式,每种方式的使用场景不同。 --- ## 认证方式对比 | 认证方式 | 用户名 | 密码 | 使用场景 | 推荐度 | |---------|--------|------|---------|--------| | **Access Token** | Access Token 值 | 留空 | 设备认证(最常用) | ⭐⭐⭐⭐⭐ | | **MQTT Basic** | 自定义用户名 | 自定义密码 | 传统 MQTT 认证 | ⭐⭐⭐ | --- ## 方式 1:Access Token 认证(推荐) ### 工作原理 - **用户名**:使用设备的 Access Token 作为 MQTT 用户名 - **密码**:留空(不设置) - **设备标识**:每个设备有唯一的 Access Token ### 为什么每个设备需要不同的 Access Token? 1. **设备身份识别** - Access Token 是设备的唯一标识符 - ThingsBoard 通过 Access Token 识别是哪个设备连接 2. **安全隔离** - 不同设备使用不同的 Token,避免设备间数据混淆 - 如果某个设备 Token 泄露,不影响其他设备 3. **权限控制** - 每个设备只能访问自己的数据 - Token 与设备 ID 绑定,自动关联设备权限 ### 连接示例 ```bash # 使用 Access Token 连接 mosquitto_pub -h localhost -p 1883 \ -t "v1/devices/me/telemetry" \ -u "ABC123DEF456GHI789J0" \ -m '{"temperature":25,"humidity":60}' # 注意:-u 后面是 Access Token,没有 -P 参数(密码留空) ``` ### Python 示例 ```python import paho.mqtt.client as mqtt # Access Token(从设备凭证中获取) ACCESS_TOKEN = "ABC123DEF456GHI789J0" client = mqtt.Client() # 使用 Access Token 作为用户名 client.username_pw_set(ACCESS_TOKEN) # 密码留空 client.connect("localhost", 1883, 60) client.publish("v1/devices/me/telemetry", '{"temperature":25}') ``` --- ## 方式 2:MQTT Basic 认证(传统用户名密码) ### 工作原理 - **用户名**:自定义用户名 - **密码**:自定义密码 - **客户端 ID**:可选的客户端 ID ### 配置步骤 1. **在 ThingsBoard Web UI 中配置** - 进入设备管理 → 选择设备 - 点击 "Manage Credentials" - 选择凭证类型:**MQTT Basic** - 填写: - Client ID(可选) - User Name(用户名) - Password(密码) 2. **连接示例** ```bash # 使用 MQTT Basic 认证连接 mosquitto_pub -h localhost -p 1883 \ -i "my-client-id" \ -t "v1/devices/me/telemetry" \ -u "my-username" \ -P "my-password" \ -m '{"temperature":25,"humidity":60}' ``` ### Python 示例 ```python import paho.mqtt.client as mqtt # MQTT Basic 认证信息 CLIENT_ID = "my-client-id" # 可选 USERNAME = "my-username" PASSWORD = "my-password" client = mqtt.Client(client_id=CLIENT_ID) client.username_pw_set(USERNAME, PASSWORD) client.connect("localhost", 1883, 60) client.publish("v1/devices/me/telemetry", '{"temperature":25}') ``` --- ## 源码分析 ### Access Token 认证流程 **位置**:`common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java` ```java private void processAuthTokenConnect(ChannelHandlerContext ctx, MqttConnectMessage connectMessage) { String userName = connectMessage.payload().userName(); // Access Token 作为用户名 // 如果密码为空,使用 Access Token 认证 // 如果密码不为空,使用 MQTT Basic 认证 } ``` **认证逻辑**:`application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java` ```java private TransportApiResponseMsg validateUserNameCredentials(...) { DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName()); if (credentials != null) { switch (credentials.getCredentialsType()) { case ACCESS_TOKEN: // Access Token 认证:用户名就是 Access Token return getDeviceInfo(credentials); case MQTT_BASIC: // MQTT Basic 认证:需要验证用户名和密码 if (VALID.equals(validateMqttCredentials(mqtt, credentials))) { return getDeviceInfo(credentials); } } } } ``` ### 认证判断逻辑 ThingsBoard 如何判断使用哪种认证方式? 1. **如果 MQTT 连接时密码为空**: - 将用户名当作 Access Token 查找设备凭证 - 如果找到且类型是 `ACCESS_TOKEN`,认证成功 2. **如果 MQTT 连接时提供了密码**: - 先尝试 Access Token 认证(用户名作为 Token) - 如果失败,尝试 MQTT Basic 认证(验证用户名+密码) --- ## 实际使用建议 ### 推荐使用 Access Token(原因) 1. **简单易用** - 只需要一个 Token,不需要管理密码 - 设备端配置简单 2. **安全性** - Token 可以随时重新生成 - 每个设备独立 Token,隔离性好 3. **ThingsBoard 设计** - 这是 ThingsBoard 的主要认证方式 - 所有文档和示例都基于 Access Token ### 使用 MQTT Basic 的场景 1. **需要兼容现有 MQTT 系统** - 如果设备已经使用用户名密码认证 - 需要与标准 MQTT Broker 兼容 2. **集中管理认证信息** - 可以使用统一的用户名密码策略 --- ## 常见问题 ### Q1: 为什么不能所有设备用同一个 Access Token? **答**: - 每个设备需要独立的身份标识 - 如果多个设备用同一个 Token,ThingsBoard 无法区分是哪个设备 - 数据会混乱,无法正确关联到设备 ### Q2: Access Token 和传统 MQTT 用户名密码有什么区别? | 特性 | Access Token | MQTT Basic | |------|-------------|------------| | 数量 | 每个设备一个 | 可以多个设备共享 | | 密码 | 不需要 | 需要 | | 管理 | ThingsBoard 自动生成 | 手动配置 | | 安全性 | 高(唯一标识) | 中(可能共享) | ### Q3: 如何查看设备的 Access Token? **方法 1:Web UI** ``` Devices → 选择设备 → Manage Credentials → 查看 Access Token ``` **方法 2:REST API** ```bash curl -X GET "http://localhost:8080/api/device/{deviceId}/credentials" \ -H "X-Authorization: Bearer $JWT_TOKEN" ``` ### Q4: 可以在同一个设备上使用两种认证方式吗? **答**:不可以。每个设备只能配置一种认证方式: - 要么使用 Access Token - 要么使用 MQTT Basic - 不能同时使用 ### Q5: 如何切换认证方式? 1. 进入设备管理 → 选择设备 2. 点击 "Manage Credentials" 3. 选择新的凭证类型 4. 配置相应的凭证信息 5. 保存 **注意**:切换后,旧凭证立即失效,设备需要重新连接。 --- ## 完整示例对比 ### 示例 1:Access Token 认证 ```bash # 设备 A(Access Token: TOKEN_A) mosquitto_pub -h localhost -p 1883 \ -t "v1/devices/me/telemetry" \ -u "TOKEN_A" \ -m '{"temperature":25}' # 设备 B(Access Token: TOKEN_B) mosquitto_pub -h localhost -p 1883 \ -t "v1/devices/me/telemetry" \ -u "TOKEN_B" \ -m '{"temperature":30}' ``` ### 示例 2:MQTT Basic 认证 ```bash # 设备 A(用户名: device-a, 密码: pass123) mosquitto_pub -h localhost -p 1883 \ -t "v1/devices/me/telemetry" \ -u "device-a" \ -P "pass123" \ -m '{"temperature":25}' # 设备 B(用户名: device-b, 密码: pass456) mosquitto_pub -h localhost -p 1883 \ -t "v1/devices/me/telemetry" \ -u "device-b" \ -P "pass456" \ -m '{"temperature":30}' ``` --- ## 总结 1. **Access Token 认证**(推荐) - 每个设备有唯一的 Access Token - 使用 Access Token 作为 MQTT 用户名,密码留空 - 简单、安全、易管理 2. **MQTT Basic 认证** - 使用传统的用户名+密码 - 适合需要兼容现有 MQTT 系统的场景 3. **选择建议** - **新项目**:使用 Access Token - **已有系统**:根据需求选择,如需兼容标准 MQTT,使用 MQTT Basic --- ## 相关文档 - [ThingsBoard MQTT API 文档](https://thingsboard.io/docs/reference/mqtt-api/) - [设备凭证管理文档](https://thingsboard.io/docs/user-guide/device-credentials/)