thingsboard/summary/23-ThingsBoard-MQTT认证机制说明.md

305 lines
7.9 KiB
Markdown
Raw Permalink Normal View History

2026-01-19 11:50:37 +08:00
# ThingsBoard MQTT 认证机制说明
## 概述
ThingsBoard 支持两种 MQTT 认证方式,每种方式的使用场景不同。
---
## 认证方式对比
| 认证方式 | 用户名 | 密码 | 使用场景 | 推荐度 |
|---------|--------|------|---------|--------|
| **Access Token** | Access Token 值 | 留空 | 设备认证(最常用) | ⭐⭐⭐⭐⭐ |
| **MQTT Basic** | 自定义用户名 | 自定义密码 | 传统 MQTT 认证 | ⭐⭐⭐ |
---
## 方式 1Access 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}')
```
---
## 方式 2MQTT 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
**答**
- 每个设备需要独立的身份标识
- 如果多个设备用同一个 TokenThingsBoard 无法区分是哪个设备
- 数据会混乱,无法正确关联到设备
### Q2: Access Token 和传统 MQTT 用户名密码有什么区别?
| 特性 | Access Token | MQTT Basic |
|------|-------------|------------|
| 数量 | 每个设备一个 | 可以多个设备共享 |
| 密码 | 不需要 | 需要 |
| 管理 | ThingsBoard 自动生成 | 手动配置 |
| 安全性 | 高(唯一标识) | 中(可能共享) |
### Q3: 如何查看设备的 Access Token
**方法 1Web UI**
```
Devices → 选择设备 → Manage Credentials → 查看 Access Token
```
**方法 2REST 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. 保存
**注意**:切换后,旧凭证立即失效,设备需要重新连接。
---
## 完整示例对比
### 示例 1Access Token 认证
```bash
# 设备 AAccess Token: TOKEN_A
mosquitto_pub -h localhost -p 1883 \
-t "v1/devices/me/telemetry" \
-u "TOKEN_A" \
-m '{"temperature":25}'
# 设备 BAccess Token: TOKEN_B
mosquitto_pub -h localhost -p 1883 \
-t "v1/devices/me/telemetry" \
-u "TOKEN_B" \
-m '{"temperature":30}'
```
### 示例 2MQTT 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/)