Azure IoT Hub MQTT订阅代码报错:连接被拒绝
解决Azure IoT Hub MQTT连接被拒绝(错误码5)的问题
从你的输出看,连接后立即被断开,错误码5对应MQTT的未授权错误,结合状态码3(服务器不可用),核心问题大概率是身份验证配置不完整或证书注册有误。以下是一步步的排查和修复方案:
1. 补上MQTT用户名的关键配置
使用X.509证书连接Azure IoT Hub时,必须指定正确格式的用户名(不需要密码,因为证书已经完成身份验证)。你的代码遗漏了这一步:
在代码中添加用户名定义,并设置到MQTT客户端:
# 新增用户名配置 username = "{}.azure-devices.net/{}/api-version=2021-04-12".format(iothub_name, device_id) # 在client.tls_set之后添加这行 client.username_pw_set(username=username, password=None)
用户名的格式是{IoT Hub主机名}/{设备ID}/api-version=2021-04-12,API版本可以使用IoT Hub支持的最新稳定版本。
2. 确认设备证书已正确注册到IoT Hub
X.509证书必须在IoT Hub中完成注册才能被信任:
- 如果是设备专属证书:
- 登录Azure门户,进入你的IoT Hub
- 找到
设备列表中的mydevice,进入详情页 - 确认认证类型为
X.509自签名或X.509 CA签名,并已上传对应证书的公钥(即你代码中的rsa_cert.pem内容)
- 如果是CA签名证书:
- 确保你已经将CA根证书上传到IoT Hub并完成验证
- 设备的证书是由该CA签发的,且设备在IoT Hub中配置为使用CA认证
3. 验证证书文件的有效性
- 检查证书文件路径是否正确,确保
root_ca、public_crt、private_key指向的文件存在且可读 - 用OpenSSL验证证书链的完整性:
如果输出openssl verify -CAfile digicertbaltimoreroot.pem rsa_cert.pemrsa_cert.pem: OK则说明证书链有效。
4. 检查设备ID和IoT Hub状态
- 确认代码中的
device_id与Azure门户中创建的设备ID完全一致(IoT Hub设备ID区分大小写) - 检查设备是否被禁用:在设备详情页查看状态是否为
启用 - 确认IoT Hub没有达到连接数限制(可在IoT Hub的指标中查看连接数)
修改后的完整代码
把上述修复点整合后的代码如下:
import paho.mqtt.client as mqtt import ssl from time import sleep root_ca = "./certs/digicertbaltimoreroot.pem" public_crt = './certs/rsa_cert.pem' private_key = './certs/rsa_private.pem' iothub_name = "myhub" device_id = "mydevice" mqtt_url = "{}.azure-devices.net".format(iothub_name) mqtt_port = 8883 topic = "devices/{}/messages/devicebound/#".format(device_id) # 新增用户名配置 username = "{}.azure-devices.net/{}/api-version=2021-04-12".format(iothub_name, device_id) def error_str(rc): return "Some error occurred. {}: {}".format(rc, mqtt.error_string(rc)) def on_disconnect(unused_client, unused_userdata, rc): print("on_disconnect", error_str(rc)) def on_connect(client, userdata, flags, response_code): print("Connected with status: {0}".format(response_code)) client.subscribe(topic, 1) def on_subscribe(client, userdata, mid, granted_qos): print("Subscribed: "+str(mid)+" "+str(granted_qos)) def on_message(client, userdata, msg): print("Topic: {0} -- Payload: {1}".format(msg.topic, str(msg.payload))) if __name__ == "__main__": client = mqtt.Client(device_id, protocol=mqtt.MQTTv311) client.tls_set(root_ca, certfile = public_crt, keyfile = private_key, cert_reqs = ssl.CERT_REQUIRED, tls_version = ssl.PROTOCOL_TLSv1_2, ciphers = None) # 设置用户名 client.username_pw_set(username=username, password=None) client.on_connect = on_connect client.on_message = on_message client.on_disconnect = on_disconnect print("Connecting to Azure IoT Hub...") client.connect(mqtt_url, mqtt_port, keepalive=60) client.loop_forever()
内容的提问来源于stack exchange,提问作者Dalton Cézar
相关产品推荐
相关产品推荐

