MQTT ClientID username/password

6 阅读7分钟
  • ClientID:与“设备连接”绑定,必须全局唯一。同一手机登不同账号需生成新值(建议使用设备 UDID + 时间戳/随机数)。
  • username/password:与“App 账号”绑定,对应不同用户的认证信息。切换账号时需同步切换凭证。
  • 核心原则:ClientID 保证“连接唯一”,username/password 保证“账号权限唯一”,两者均不能固定写死。

这样设置后,不同账号登录同一手机 App,既能稳定连接 MQTT Broker,又能实现数据隔离(A 账号无法看到 B 账号的设备)。


一、核心结论

username / password 是 MQTT Broker 的身份认证凭证,其来源只有以下 3 类:

  1. 测试阶段(公共免费 Broker) → 无需填写(留空)
  2. 商用阶段(云厂商 Broker,如阿里云/腾讯云) → 由云厂商为每个“用户/设备”生成
  3. 自建 Broker → 由你在 Broker 后台自行配置

二、分场景拆解(来源 + 取值 + 实战)

场景1:测试阶段(公共免费 Broker,如 broker.emqx.io

  • 来源:不需要设置,直接留空。
    公共测试 Broker 关闭了认证功能,任何合法 ClientID 均可连接。
  • 实战代码
    private let username: String? = nil
    private let password: String? = nil
    
    mqttClient.username = username
    mqttClient.password = password
    
  • 注意:仅限本地调试,不能用于正式产品(存在消息篡改/伪造风险)。

场景2:商用阶段(云厂商 MQTT Broker)

方式A:按“用户账号”分配(多设备归属于一个用户)

  • 来源
    在云厂商控制台创建“用户账号”,或通过 App 后台调用云厂商 API 自动生成。
  • 取值规则
    • username:用户ID + 固定前缀,如 user_10086
    • password:云厂商生成的随机字符串(如 a9s8d7f6g5h4j3k2l1)或加密字符串
  • 实战示例
    用户手机号 13800138000 注册后,App 后台调用阿里云 IoT API 生成凭证,返回:
    • username = 13800138000
    • password = AliYun_MQTT_8888

方式B:按“设备”分配(每个设备独立认证)

  • 来源
    在云厂商控制台为每台设备创建“设备证书”(DeviceName / DeviceSecret)。

  • 取值规则(以阿里云为例):

    • usernameDeviceName&ProductKey,如 light001&a1b2c3d4e5f6
    • password:通过 ProductKeyDeviceNameDeviceSecret 经 HMAC-SHA1 加密生成
  • 实战示例

    1. 创建产品,ProductKey = a1b2c3d4e5f6
    2. 添加设备 light001,生成 DeviceSecret = s7890fghjkl
    3. 计算 password(使用云厂商工具)
    4. App 绑定设备后,从服务器获取凭证用于 MQTT 连接
  • 关键工具

场景3:自建 MQTT Broker(如 EMQX / Mosquitto)

手动创建方式

  1. 登录 Broker 管理后台(如 EMQX Dashboard)
  2. 进入「认证授权」→「用户管理」
  3. 手动输入自定义的 usernamepassword
  4. App 连接时使用该凭证

动态生成方式(对接自己的用户体系)

  • 流程

    1. App 后台提供接口,用户注册时调用 Broker 的 REST API(如 EMQX)
    2. 自动创建 MQTT 账号(如 username = 手机号password = 随机字符串
    3. 返回凭证给 App 用于 MQTT 连接
  • API 示例(EMQX)

    curl -X POST http://你的BrokerIP:18083/api/v5/auth/users \
      -u admin:public \
      -H "Content-Type: application/json" \
      -d '{
        "username": "13800138000",
        "password": "123456",
        "tags": { "user_id": "10086" }
      }'
    

三、实战总结

开发阶段username/password 来源取值示例
测试留空(无需设置)nil / ""
商用(云厂商)云厂商为用户/设备生成username=light001&a1b2c3d4e5f6
password=加密字符串
自建 Broker自己在 Broker 后台创建 / API 生成username=13800138000
password=123456abc

四、核心注意事项

  1. 绝对不能硬编码
    凭证必须在用户登录后从 App 后台动态获取,不可写死在代码中(否则可被反编译泄露)。

  2. 加密存储
    获取到的 password 应存入 iOS 的 Keychain,不要存在沙盒或偏好设置中。

  3. 权限隔离
    不同用户/设备的凭证需严格隔离,确保 A 用户的凭证无法访问 B 用户的设备。

简单来说:username / password 就是 MQTT Broker 的“登录账号密码”——测试时不用登,商用时找云厂商要,自建时自己配,核心是保证 只有合法用户/设备能连接

已按要求去除具体品牌名称(如 Anker、eufy 等),保留通用逻辑,重新整理如下:


核心结论

参数是否由云平台直接返回?具体来源/生成逻辑
ClientID❌ 本地生成App使用“云平台返回的设备SN/用户ID + 设备UDID + 时间戳”拼接(保证全局唯一)
username✅ 部分返回 + 本地拼接云平台返回设备SN/用户ID/ProductKey,App按厂商规则拼接
password/token✅ 云平台返回(原材料)云平台返回设备Secret/用户AccessToken,App按规则加密计算

智能硬件「配网+绑定」全流程(参数来源详解)

步骤1:设备配网(设备连接WiFi)

  • 场景:用户在App中点击“添加设备”,设备进入配网模式
  • App操作:用户输入WiFi账号/密码,App通过声波/蓝牙将WiFi信息 + Broker地址发送给设备
  • 云平台返回给App: ✅ 设备唯一标识:DeviceSNProductKey ✅ 设备临时认证密钥:DeviceSecret
  • App本地操作:暂存信息(尚未生成MQTT参数)

步骤2:设备激活(设备连接云平台)

  • 场景:设备使用收到的WiFi信息联网,主动连接MQTT Broker
  • 设备操作:使用出厂预烧的DeviceSN + DeviceSecret向云平台发送激活请求
  • 云平台返回给设备: ✅ 长期认证凭证(如mTLS证书、永久Secret) ✅ 设备专属Topic白名单
  • 云平台同步给App: ✅ 设备激活状态(“已激活”) ✅ 设备与用户账号的绑定关系

步骤3:App绑定设备(生成MQTT连接参数)

  • 云平台返回给App

    1. 用户级凭证:UserIDUserAccessToken
    2. 设备级凭证:DeviceSNDeviceSecretProductKey
    3. Broker地址
  • App本地生成MQTT参数(关键代码示例):

    // 1. 生成ClientID(本地拼接,保证唯一)
    let deviceUDID = UIDevice.current.identifierForVendor!.uuidString
    let timestamp = String(Date().timeIntervalSince1970)
    let clientID = "app_\(deviceUDID)_\(UserID)_\(DeviceSN)_\(timestamp)"
    
    // 2. 生成username(拼接云平台返回值)
    let username = "\(DeviceSN)&\(ProductKey)&\(UserID)"
    
    // 3. 生成password(加密计算)
    let rawStr = "\(UserAccessToken)\(DeviceSecret)\(timestamp)"
    let password = rawStr.hmacSHA256()  // 使用HMAC-SHA256加密
    

1. 为什么不直接返回 ClientID?

  • 云平台无法预知App的运行环境(如手机UDID、当前时间戳)
  • ClientID需要“全局唯一 + 与设备/用户绑定”,App本地生成更灵活
  • 若云端返回固定ClientID,多手机登录同一账号时会冲突(Broker踢线下线)

2. 为什么 password 是“计算后的值”而非直接返回?

  • 云平台不返回明文password,避免传输过程被劫持
  • 仅返回“加密原材料”(如DeviceSecret、AccessToken)
  • App本地按约定算法(如HMAC-SHA256)计算,使password动态变化(每次登录不同),提升安全性

3. 配网绑定后,后续登录如何获取参数?

  • 首次绑定:云平台返回核心凭证,App存入Keychain(加密存储)
  • 后续登录:App从Keychain读取DeviceSN/UserID/DeviceSecret等,本地重新生成ClientID/username/password,无需重新配网

总结

  1. 配网绑定时,云平台返回的是核心原材料(DeviceSN、UserID、Secret、AccessToken),而非可直接使用的MQTT参数
  2. ClientID 由App本地拼接(UDID + 用户/设备ID + 时间戳),保证唯一性
  3. username 是原材料的拼接结果,password 是原材料的加密计算结果,两者都依赖云平台返回的凭证
  4. 核心原则:云平台管理“身份凭证”,App负责“参数生成” — 既保证安全,又避免ClientID冲突