帮你快速理解、总结文档立即下载

设备证书认证

最近更新时间:2026-09-11 16:05:33
我的收藏
本文将介绍设备如何使用 ProductID、DeviceName、设备证书和设备私钥建立 MQTT 安全连接,并完成设备身份认证和上线。

功能介绍

设备证书认证使用平台为每台设备颁发的设备证书和设备私钥验证设备身份。设备连接平台时,通过 CA 证书验证服务器身份,同时向平台提供设备证书并使用设备私钥证明设备身份。双向 TLS 认证通过后,设备即可建立 MQTT 连接并上线。
证书认证采用非对称加密,安全性较高,但要求设备支持 X.509 证书解析及 TLS 连接。
注意:
设备私钥属于敏感凭证,请妥善保管。CA 证书和设备证书可以公开分发,但不得泄露设备私钥。
如果尚未确定使用设备证书认证还是设备密钥认证,请参见 认证方式概览

认证流程

设备证书认证流程参见下图:


认证参数

设备证书认证涉及“设备身份参数”、“证书文件”和“MQTT 连接参数”三类参数。
如需在控制台创建证书认证设备,并获取设备证书、设备私钥、腾讯云 CA 证书及设备身份信息,请参见 获取设备三元组

设备身份参数

参数
参数来源
说明
是否保密
ProductID
产品详情页或设备详情页。
标识设备所属产品。
DeviceName
设备详情页。
标识产品下的具体设备。
ProductID 与 DeviceName 组合后形成平台中的设备唯一标识。

证书文件

文件
获取方式
作用
是否保密
设备证书
创建设备后由平台颁发。
向平台声明设备身份。
设备私钥
创建设备后由平台颁发。
证明设备持有对应设备证书。
CA 证书
平台证书下载入口。
验证物联网开发平台服务器身份。
设备证书与设备私钥必须配套使用,不能混用不同设备的证书和私钥。
注意:
请在设备凭证生成后及时下载并安全保存设备私钥。设备私钥不得写入公开代码、日志、截图或普通配置文件。
证书文件参考:


MQTT 连接参数

参数
取值或生成方式
说明
Broker Address
广州:${ProductID}.iotcloud.tencentdevices.com
曼谷:${ProductID}.ap-bangkok.iothub.tencentdevices.com
MQTT 服务器地址。
Broker Port
8883
证书认证设备接入端口。
Client ID
${ProductID}${DeviceName}
ProductID 与 DeviceName 直接拼接。
Username
${ClientID};${sdkappid};${connid};${expiry}
MQTT 连接用户名。
Password
可填写任意非空值
证书认证不校验 Password 内容。
KeepAlive
0~900秒
MQTT 连接保活时间。
${}表示变量,不是实际的拼接字符。连接域名和端口应以设备所属地域及控制台当前信息为准。
Username 中各字段的含义如下:
字段
说明
sdkappid
固定填写12010126
connid
客户端生成的随机字符串,用于区分连接。
expiry
连接参数的过期时间,使用 Unix 时间戳,单位为秒。
证书认证不使用 DeviceSecret,也不需要对 Username 进行 HMAC 签名。Password 不会参与设备证书校验,但仍需按照 MQTT 客户端的要求设置一个非空值。

证书有效期与更新

设备证书和平台 CA 证书均存在有效期。生产环境应建立证书有效期检查及更新机制,避免证书到期导致设备无法连接平台。

平台 CA 证书

平台 CA 证书由物联网开发平台提供,用于设备验证 MQTT 服务器证书,不属于单台设备的身份凭证,可供使用相同平台信任链的设备复用。
平台 CA 证书发生更新时:
使用官方设备端 SDK 的设备,应根据平台通知升级至支持新 CA 证书的 SDK 版本,并通过固件升级部署至设备。
使用自研 MQTT 客户端的设备,应从物联网开发平台控制台或官方文档获取最新 CA 证书,并通过固件升级或 OTA 更新设备端信任库。
平台不会自动将新 CA 证书写入存量设备,用户需要自行完成设备侧证书更新。
生产设备应具备远程更新 CA 证书的能力,并根据平台发布的更新时间安排升级,避免存量设备集中断连。
设备证书和 CA 证书均具有有效期。设备建立 TLS 连接时,平台会校验设备证书是否处于有效期内,设备也会通过 CA 证书校验平台服务器证书。
可以使用以下命令查看证书有效期:
请先下载证书文件,并在证书文件的目录下打开终端,执行:
# Windows PowerShell
certutil -dump "证书文件名"

# Linux && macOS Shell
openssl x509 -in "证书文件名" -noout -dates

# 查看输出结果
...
notBefore= # 证书有效起始时间
notAfter= # 证书有效结束时间
...
# 示例
# 腾讯云证书名称:ca.crt
# 设备证书名称:certificate_authentication_device_cert.crt

# Windows PowerShell
certutil -dump ca.crt
certutil -dump certificate_authentication_device_cert.crt

# Linux && macOS Shell
openssl x509 -in ca.crt -noout -dates
openssl x509 -in certificate_authentication_device_cert.crt -noout -dates

# 查看输出结果
...
notBefore= # 证书有效起始时间
notAfter= # 证书有效结束时间
...

生成 MQTT 连接参数

设备详情页如已提供完整 MQTT 连接参数,可直接复制使用。也可以根据 ProductID 和 DeviceName 生成 Client ID 与 Username。
生成关系如下:
Client ID = ProductID + DeviceName

Username = ClientID + ";12010126;" + connid + ";" + expiry

Password = 任意非空字符串
示例:
ProductID = testProductID
DeviceName = testDeviceName
connid = A1B2C
expiry = 1786610239

Client ID = testProductIDtestDeviceName
Username = testProductIDtestDeviceName;12010126;A1B2C;1786610239
Password = certificate
说明:
以上参数仅用于说明拼接规则,不能用于连接真实设备。

安全注意事项

每台设备应使用独立的设备证书和设备私钥。
不得在日志文件、截图、工单或公开的代码仓库中暴露设备私钥。
设备私钥建议保存在安全芯片或受保护的存储区域中。
设备证书与设备私钥必须配套使用,不得在不同的设备之间复制使用。
不得通过 tls_insecure_set(True) 关闭服务器证书校验。
设备应维护正确的系统时间,避免证书校验或连接参数校验出现异常。
调试完成后,应删除临时复制的设备私钥文件。
当设备私钥发生泄露时,应及时禁用设备并重新发放设备凭证。

使用 Python 连接平台

本节使用 Python 脚本连接物联网开发平台。当脚本返回认证成功且控制台设备状态显示为在线时,即表示设备证书认证接入完成。
本示例仅验证设备认证和上线,不包含 Topic 发布、订阅及物模型消息通信。

前提条件

开始接入前,请确认已完成以下准备:
已创建认证方式为证书认证的产品。
已在产品下创建设备。
已获得 ProductID 和 DeviceName
已下载当前设备的设备证书和设备私钥
已下载平台提供的设备端 CA 证书
本地环境已安装 Python 3
本地网络能够访问平台 MQTT 接入域名。
设备系统时间正确。

准备运行环境

建议在虚拟环境中安装依赖和运行代码。
安装 Paho MQTT 客户端:
# Windows powershell
python -m pip install "paho-mqtt>=2.1,<3.0"

# Linux && macOS shell
python3 -m pip install "paho-mqtt>=2.1,<3.0"
Paho MQTT 是 Python MQTT 客户端库。本示例使用 MQTT 3.1.1 及 Callback API VERSION2。
安装完成后,可执行以下命令确认版本:
# Windows PowerShell
python -m pip show paho-mqtt

# Linux && macOS Shell
python3 -m pip show paho-mqtt

# 输出中的 Version 应为 2.1.0。

创建连接脚本

将以下代码保存为mqtt_cert_connect.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import secrets
import ssl
import string
import sys
import time
from pathlib import Path

try:
import paho.mqtt.client as mqtt
except ImportError:
mqtt = None


SDK_APP_ID = "12010126"

# 凭证只能从脚本同级的cert目录中读取。
SCRIPT_DIR = Path(__file__).resolve().parent
CERT_DIR = (SCRIPT_DIR / "cert").resolve()


def required_input(prompt):
"""读取必填参数并清除首尾空格。"""
value = input(prompt).strip()
if not value:
raise ValueError("输入内容不能为空")
return value


def get_cert_file(prompt):
"""根据用户输入的文件名,从cert目录中读取凭证文件。"""
filename = required_input(prompt)

# 只允许输入文件名,不允许输入目录或绝对路径。
if (
Path(filename).is_absolute()
or "/" in filename
or "\\\\" in filename
or filename in {".", ".."}
):
raise ValueError(
"只允许输入cert目录中的文件名,不能包含路径"
)

file_path = (CERT_DIR / filename).resolve()

# 防止通过符号链接等方式访问cert目录外的文件。
try:
file_path.relative_to(CERT_DIR)
except ValueError as exc:
raise ValueError(
"凭证文件必须位于脚本同级的cert目录中"
) from exc

if not file_path.is_file():
raise FileNotFoundError(
f"在cert目录中未找到文件:{filename}"
)

try:
with file_path.open("rb") as file:
file.read(1)
except OSError as exc:
raise PermissionError(
f"无法读取凭证文件:{filename}"
) from exc

return file_path


def generate_connid(length=5):
"""生成用于区分MQTT连接的随机字符串。"""
alphabet = string.ascii_uppercase + string.digits
return "".join(secrets.choice(alphabet) for _ in range(length))


def main():
if mqtt is None:
raise ImportError(
'未安装paho-mqtt,请执行:'
'python3 -m pip install "paho-mqtt>=2.1,<3.0"'
)

if not CERT_DIR.is_dir():
raise FileNotFoundError(
f"未找到cert目录,请创建:{CERT_DIR}"
)

print("请输入cert目录中的凭证文件名。")
print(f"凭证目录:{CERT_DIR}\\n")

ca_file = get_cert_file("CA证书文件名:")
device_cert_file = get_cert_file("设备证书文件名:")
device_key_file = get_cert_file("设备私钥文件名:")

print("\\n已加载以下凭证文件:")
print(f"- CA证书:{ca_file.name}")
print(f"- 设备证书:{device_cert_file.name}")
print(f"- 设备私钥:{device_key_file.name}")

broker = required_input("\\nMQTT服务器地址:")

port_text = input("端口号(直接回车使用8883):").strip()
port = int(port_text) if port_text else 8883

product_id = required_input("ProductID:")
device_name = required_input("DeviceName:")

client_id = f"{product_id}{device_name}"
connid = generate_connid()
expiry = int(time.time()) + 60 * 60

username = (
f"{client_id};{SDK_APP_ID};{connid};{expiry}"
)

# 证书认证不校验Password内容。
password = "certificate"

def on_connect(
client,
userdata,
connect_flags,
reason_code,
properties,
):
if reason_code == 0:
print("\\n认证成功,设备已连接物联网开发平台。")
print("请前往控制台查看设备在线状态。")
else:
print(f"\\nMQTT连接失败,返回码:{reason_code}")
client.disconnect()

def on_connect_fail(client, userdata):
print(
"\\n网络连接或TLS握手失败,"
"请检查服务器地址、端口及凭证文件。"
)

def on_disconnect(
client,
userdata,
disconnect_flags,
reason_code,
properties,
):
if reason_code != 0:
print(f"\\n连接异常断开,返回码:{reason_code}")

client = mqtt.Client(
callback_api_version=mqtt.CallbackAPIVersion.VERSION2,
client_id=client_id,
clean_session=True,
protocol=mqtt.MQTTv311,
)

client.username_pw_set(
username=username,
password=password,
)

client.tls_set(
ca_certs=str(ca_file),
certfile=str(device_cert_file),
keyfile=str(device_key_file),
cert_reqs=ssl.CERT_REQUIRED,
tls_version=ssl.PROTOCOL_TLS_CLIENT,
)

# 启用服务器证书及域名校验。
client.tls_insecure_set(False)

client.on_connect = on_connect
client.on_connect_fail = on_connect_fail
client.on_disconnect = on_disconnect

print(f"\\n正在连接:{broker}:{port}")
print(f"ClientId:{client_id}")
print("程序将保持连接,按Ctrl+C退出。")

client.connect(
host=broker,
port=port,
keepalive=60,
)

try:
client.loop_forever()
finally:
client.disconnect()


if __name__ == "__main__":
try:
sys.exit(main())
except KeyboardInterrupt:
print("\\n用户终止连接。")
sys.exit(0)
except Exception as exc:
print(f"\\n运行失败:{exc}")
sys.exit(1)
该脚本仅读取证书文件,不会复制或保存证书内容,也不会将认证参数写入配置文件。

准备证书文件

将以下文件放置在mqtt_cert_connect.py 同目录的cert
├─ mqtt_cert_connect.py
└─ cert/
├─ ca.crt
├─ device.crt
└─ device.key
其中:
ca.crt 表示平台 CA证书。
device.crt 表示当前设备的设备证书。
device.key 表示与设备证书配套的设备私钥。
说明:
以上名称仅为示例,运行脚本时请输入实际文件名。

运行连接脚本

# Windows PowerShell
python mqtt_cert_connect.py

# Linux && macOS Shell
python3 mqtt_cert_connect.py
运行后依次输入:
# 运行示例
凭证目录:D:\\test\\shell\\test_cert\\cert

CA证书文件名:ca.crt
设备证书文件名:certificate_authentication_device_cert.crt
设备私钥文件名:certificate_authentication_device_private.key

已加载以下凭证文件:
- CA证书:ca.crt
- 设备证书:certificate_authentication_device_cert.crt
- 设备私钥:certificate_authentication_device_private.key

MQTT服务器地址:ProductID.iotcloud.tencentdevices.com
端口号(直接回车使用8883):8883
ProductID:ProductID
DeviceName:certificate_authentication_device
连接成功时,程序输出类似:
正在连接:******.iotcloud.tencentdevices.com:8883
ClientId:******
程序将保持连接,按Ctrl+C退出。

认证成功,设备已连接物联网开发平台。
请前往控制台查看设备在线状态。
程序会持续运行并保持 MQTT 连接。需要断开连接时,按下Ctrl+C

验证设备上线

设备发起 MQTT 连接后,如需在控制台确认设备状态及查看上下线记录,请参见 查看设备状态和上下线日志

问题排查

网络连接失败

检查以下内容:
Broker Address 是否与设备详情页或当前地域接入地址一致。
端口号是否为证书认证端口 8883。
本地 DNS 是否能够解析 MQTT 服务器域名。
防火墙或网络策略是否限制对目标域名和端口的访问。
相关域名是否已加入访问白名单。

TLS 握手失败

检查以下内容:
是否加载了平台提供的正确的 CA 证书。
设备证书与设备私钥是否属于同一台设备。
设备证书文件或私钥文件是否损坏。
证书文件的路径是否正确。
设备是否具有读取证书文件和私钥文件的权限。
设备的系统时间是否正确。
是否错误关闭了服务器证书校验或域名校验。

MQTT 连接失败

检查以下内容:
ProductID 和 DeviceName 是否属于当前的设备。
Client ID 是否由 ProductID 和 DeviceName 直接拼接而成。
Username 中指定的 Client ID 是否与连接时使用的 Client ID 一致。
Username 中的 sdkappid 是否为 12010126。
Username 中的 expiry 字段是否已过期。
当前产品是否采用了证书认证。
设备证书是否已经失效。

证书与私钥不匹配

如果 TLS 握手提示证书错误或私钥错误,请确认:
未混用不同设备的证书和私钥。
私钥文件的内容完整。
文件的格式能够被当前的 TLS 客户端识别。
私钥未在复制、换行或编码转换的过程中损坏。

脚本连接成功,但设备未显示在线

检查以下内容:
是否进入了正确的实例和正确的设备详情页。
Client ID 是否对应了当前的 DeviceName。
连接脚本是否仍在运行。
设备的上下线日志中是否存在新的连接记录。
是否有另一个客户端使用相同的 Client ID 建立了连接。