2. IoT Hub实例创建与设备注册

在上一节中我们已经理解了 IoT Hub 在设备接入链路中的角色:它是设备与云端之间的双向通信入口,负责身份认证、消息路由和状态管理。本节要把这个概念落到可操作的对象上——一个真实存在的 IoT Hub 实例,以及注册在它下面的设备标识。只有实例和设备标识都就绪,后续的遥测上报、命令下发、设备孪生才有承载对象。

创建 IoT Hub 实例:先确定命名与层级

IoT Hub 实例在 Azure 中是一个全局唯一的资源,它的主机名形如 {hub-name}.azure-devices.net,因此 hub-name 必须在所有 Azure 租户中唯一。命名建议采用“项目-环境-区域”的组合,例如 iothub-lab-dev-eastasia,避免使用纯数字或过短名称。创建时需要确定几个关键参数:订阅、资源组、区域、定价层(Free / Basic / Standard)。Free 层每个订阅只能有一个,适合实验;Standard 层支持设备孪生、直接方法和云到设备消息,是工程接入的常用选择。

通过门户创建时,在“创建 IoT Hub”页面依次填写订阅、资源组、区域、名称,然后在“管理”页签选择定价层和单位数。单位数决定每日消息配额,实验阶段 1 个单位即可。创建完成后,在“概览”页可以看到主机名、定价层和位置,这些信息后续会用于连接字符串和 SDK 配置。

通过 CLI 创建则更适合可重复的工程流程。先确认已登录并选择正确订阅:

az login
az account set --subscription "<subscription-id>"
az group create --name rg-iot-lab --location eastasia
az iot hub create \
  --name iothub-lab-dev-eastasia \
  --resource-group rg-iot-lab \
  --location eastasia \
  --sku S1 \
  --unit 1

执行成功后,用 az iot hub show --name iothub-lab-dev-eastasia --query hostName -o tsv 可以取出主机名,确认实例已就绪。这里要注意:CLI 创建是幂等的,重复执行同名命令不会产生第二个实例,但会返回已有实例的信息,适合放进脚本。

设备标识注册:为每台设备建立唯一身份

IoT Hub 中的“设备”并不是物理设备的自动发现结果,而是需要显式注册的设备标识(device identity)。每个设备标识包含 deviceId、认证方式(对称密钥、X.509 证书或 TPM)和状态(enabled / disabled)。设备只有用与 deviceId 匹配的凭据才能连接,否则会在 TLS 握手后的认证阶段被拒绝。

门户注册的路径是:进入 IoT Hub → “设备” → “+ 添加设备” → 填写设备 ID(例如 sensor-001)→ 选择对称密钥 → 保存。保存后设备列表中会出现该设备,状态为 enabled。CLI 注册等价命令为:

az iot hub device-identity create \
  --hub-name iothub-lab-dev-eastasia \
  --device-id sensor-001 \
  --auth-method shared_private_key

注册完成后,可以用 az iot hub device-identity list --hub-name iothub-lab-dev-eastasia -o table 查看设备列表,确认 deviceId、状态和认证方式。如果设备需要临时停用,把状态改为 disabled 即可,此时设备连接会被拒绝,但设备标识和密钥仍然保留,便于恢复。

连接字符串生成:从设备标识到可连接凭据

设备连接字符串是设备端 SDK 初始化时使用的核心凭据,格式为:

HostName={hub-name}.azure-devices.net;DeviceId={device-id};SharedAccessKey={base64-key}

它由三部分组成:Hub 主机名、设备 ID 和设备主密钥。门户中在设备详情页可以直接复制“主连接字符串”;CLI 中则用:

az iot hub device-identity connection-string show \
  --hub-name iothub-lab-dev-eastasia \
  --device-id sensor-001 \
  --output tsv

需要区分两类连接字符串:设备连接字符串用于设备端,只包含该设备的权限;IoT Hub 级连接字符串(包含 iothubowner 或服务策略)用于服务端 SDK,权限更大,绝不能下发到设备。工程中常见的错误就是把 Hub 级连接字符串写进设备固件,导致一台设备泄露即可控制整个 Hub。

设备主密钥一旦泄露,攻击者可以伪造该设备身份接入并发送消息。生产环境应优先使用 X.509 证书或 TPM 认证,并定期轮换密钥。

安全存储:连接字符串不能硬编码

连接字符串属于机密,不能出现在源码、镜像或日志中。设备端常见的做法是:在设备首次启动时通过安全注入(如出厂配置、安全烧录或 DPS 注册)写入,运行时存放在受保护的位置。Linux 设备可放在仅 root 可读的文件中并设置权限 chmod 600;Windows 设备可使用 DPAPI 加密;资源受限设备可写入受保护的 Flash 分区。云端服务端则使用 Azure Key Vault 保存 Hub 级连接字符串,应用通过托管标识读取,避免在配置文件中明文存放。

下面这张图把本节的关键对象和凭据流向串起来:从创建 Hub、注册设备标识,到生成设备连接字符串,再到设备端安全存储与服务端 Key Vault 的分工。

IoT Hub 实例创建与设备注册的凭据链路 ① 创建 IoT Hub 实例 门户 / az iot hub create 名称全局唯一 主机名: xxx.azure-devices.net ② 注册设备标识 deviceId: sensor-001 认证: 对称密钥 / X.509 状态: enabled ③ 生成连接字符串 HostName=... DeviceId=sensor-001 SharedAccessKey=*** 设备端安全存储 Linux: /etc/iot/device.key chmod 600 Windows: DPAPI 加密存储 受限设备: 受保护 Flash 分区 服务端凭据管理 Azure Key Vault 保存 Hub 级连接串 应用通过托管标识读取 禁止写入源码 / 镜像 / 日志 注意:设备连接字符串只授予单设备权限;Hub 级连接字符串权限更大,绝不能下发到设备

验证与常见判断依据

完成上述步骤后,可以用一个最小验证确认链路可用:在设备端用连接字符串初始化 SDK,发送一条遥测消息,然后在门户的“设备”详情页查看“最近活动时间”是否更新,或用 az iot hub monitor-events --hub-name iothub-lab-dev-eastasia 观察消息是否到达。如果连接失败,优先检查三点:deviceId 是否与注册一致、连接字符串是否被截断或包含多余空格、设备状态是否为 enabled。认证失败通常返回 401,而主机名错误则表现为 DNS 解析失败或 TLS 握手异常,这两类问题的排查方向完全不同。