7.9 KiB
7.9 KiB
ThingsBoard MQTT 认证机制说明
概述
ThingsBoard 支持两种 MQTT 认证方式,每种方式的使用场景不同。
认证方式对比
| 认证方式 | 用户名 | 密码 | 使用场景 | 推荐度 |
|---|---|---|---|---|
| Access Token | Access Token 值 | 留空 | 设备认证(最常用) | ⭐⭐⭐⭐⭐ |
| MQTT Basic | 自定义用户名 | 自定义密码 | 传统 MQTT 认证 | ⭐⭐⭐ |
方式 1:Access Token 认证(推荐)
工作原理
- 用户名:使用设备的 Access Token 作为 MQTT 用户名
- 密码:留空(不设置)
- 设备标识:每个设备有唯一的 Access Token
为什么每个设备需要不同的 Access Token?
-
设备身份识别
- Access Token 是设备的唯一标识符
- ThingsBoard 通过 Access Token 识别是哪个设备连接
-
安全隔离
- 不同设备使用不同的 Token,避免设备间数据混淆
- 如果某个设备 Token 泄露,不影响其他设备
-
权限控制
- 每个设备只能访问自己的数据
- Token 与设备 ID 绑定,自动关联设备权限
连接示例
# 使用 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 示例
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
配置步骤
-
在 ThingsBoard Web UI 中配置
- 进入设备管理 → 选择设备
- 点击 "Manage Credentials"
- 选择凭证类型:MQTT Basic
- 填写:
- Client ID(可选)
- User Name(用户名)
- Password(密码)
-
连接示例
# 使用 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 示例
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
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
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 如何判断使用哪种认证方式?
-
如果 MQTT 连接时密码为空:
- 将用户名当作 Access Token 查找设备凭证
- 如果找到且类型是
ACCESS_TOKEN,认证成功
-
如果 MQTT 连接时提供了密码:
- 先尝试 Access Token 认证(用户名作为 Token)
- 如果失败,尝试 MQTT Basic 认证(验证用户名+密码)
实际使用建议
推荐使用 Access Token(原因)
-
简单易用
- 只需要一个 Token,不需要管理密码
- 设备端配置简单
-
安全性
- Token 可以随时重新生成
- 每个设备独立 Token,隔离性好
-
ThingsBoard 设计
- 这是 ThingsBoard 的主要认证方式
- 所有文档和示例都基于 Access Token
使用 MQTT Basic 的场景
-
需要兼容现有 MQTT 系统
- 如果设备已经使用用户名密码认证
- 需要与标准 MQTT Broker 兼容
-
集中管理认证信息
- 可以使用统一的用户名密码策略
常见问题
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
curl -X GET "http://localhost:8080/api/device/{deviceId}/credentials" \
-H "X-Authorization: Bearer $JWT_TOKEN"
Q4: 可以在同一个设备上使用两种认证方式吗?
答:不可以。每个设备只能配置一种认证方式:
- 要么使用 Access Token
- 要么使用 MQTT Basic
- 不能同时使用
Q5: 如何切换认证方式?
- 进入设备管理 → 选择设备
- 点击 "Manage Credentials"
- 选择新的凭证类型
- 配置相应的凭证信息
- 保存
注意:切换后,旧凭证立即失效,设备需要重新连接。
完整示例对比
示例 1:Access Token 认证
# 设备 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 认证
# 设备 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}'
总结
-
Access Token 认证(推荐)
- 每个设备有唯一的 Access Token
- 使用 Access Token 作为 MQTT 用户名,密码留空
- 简单、安全、易管理
-
MQTT Basic 认证
- 使用传统的用户名+密码
- 适合需要兼容现有 MQTT 系统的场景
-
选择建议
- 新项目:使用 Access Token
- 已有系统:根据需求选择,如需兼容标准 MQTT,使用 MQTT Basic