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

7.9 KiB
Raw Blame History

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 绑定,自动关联设备权限

连接示例

# 使用 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}')

方式 2MQTT Basic 认证(传统用户名密码)

工作原理

  • 用户名:自定义用户名
  • 密码:自定义密码
  • 客户端 ID:可选的客户端 ID

配置步骤

  1. 在 ThingsBoard Web UI 中配置

    • 进入设备管理 → 选择设备
    • 点击 "Manage Credentials"
    • 选择凭证类型:MQTT Basic
    • 填写:
      • Client ID可选
      • User Name用户名
      • Password密码
  2. 连接示例

# 使用 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 如何判断使用哪种认证方式?

  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

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 认证

# 设备 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 认证

# 设备 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

相关文档