你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

快速入门 - 预配 X.509 证书模拟设备

在本快速入门中,你将在 Windows 计算机上创建一台模拟设备。 模拟设备被配置为使用 X.509 证书证明进行身份验证。 配置设备后,你将随后使用 Azure IoT 中心设备预配服务将其预配到 IoT 中心。

如果不熟悉预配过程,请查看预配概述。 另外,在继续操作之前,请确保已完成通过 Azure 门户设置 IoT 中心设备预配服务中的步骤。

本快速入门演示适用于基于 Windows 工作站的解决方案。 但是,也可以在 Linux 上执行这些过程。 有关 Linux 示例,请参阅教程:预配地理延迟

先决条件

以下先决条件适用于 Windows 开发环境。 对于 Linux 或 macOS,请参阅 SDK 文档的准备开发环境中的相应部分。

  • 安装 Visual Studio 2022 并启用“使用 C++ 的桌面开发”工作负载。 Visual Studio 2015、Visual Studio 2017 和 Visual Studio 2019 也受支持。 对于 Linux 或 macOS,请参阅 SDK 文档的准备开发环境中的相应部分。

  • 安装最新的 CMake 生成系统。 请确保选中将 CMake 可执行文件添加到路径的选项。

    重要

    在开始 CMake 安装之前,请确认在计算机上安装 Visual Studio 必备组件(Visual Studio 和“使用 C++ 的桌面开发”工作负载)。 满足先决条件并验证下载内容后,安装 CMake 生成系统。 另请注意旧版本的 CMake 生成系统无法生成本文中使用的解决方案文件。 请确保使用最新版本的 CMake。

以下先决条件适用于 Windows 开发环境。 对于 Linux 或 macOS,请参阅 SDK 文档的准备开发环境中的相应部分。

  • 在基于 Windows 的计算机上安装 .NET SDK 6.0 或更高版本。 可使用以下命令来检查你的版本。

    dotnet --info
    

以下先决条件适用于 Windows 开发环境。 对于 Linux 或 macOS,请参阅 SDK 文档的准备开发环境中的相应部分。

以下先决条件适用于 Windows 开发环境。

以下先决条件适用于 Windows 开发环境。 对于 Linux 或 macOS,请参阅 SDK 文档的准备开发环境中的相应部分。

  • 安装最新版本的 Git。 确保将 Git 添加到可供命令窗口访问的环境变量。 请参阅软件自由保护组织提供的 Git 客户端工具,了解要安装的最新版 git 工具,其中包括 Git Bash,这是一个命令行应用,可以用来与本地 Git 存储库交互。

  • 确保计算机上安装了 OpenSSL。 在 Windows 上, Git 安装包含 OpenSSL 安装。 可以从 Git Bash 提示符访问 OpenSSL。 若要验证是否安装了 OpenSSL,请打开 Git Bash 提示符并输入 openssl version

    注意

    除非你熟悉 OpenSSL 并且已将其安装在 Windows 计算机上,否则我们建议从 Git Bash 提示符使用 OpenSSL。 或者,可以选择下载源代码并生成 OpenSSL。 若要了解详细信息,请参阅 OpenSSL 下载页。 或者,可以从第三方下载预生成的 OpenSSL。 若要了解详细信息,请参阅 OpenSSL wiki。 Microsoft 不保证从第三方下载的包的有效性。 如果你确实选择生成或下载 OpenSSL,请确保可在你的路径中访问 OpenSSL 二进制文件,并且 OPENSSL_CNF 环境变量设置为 openssl.cnf 文件的路径。

  • 打开 Windows 命令提示符和 Git Bash 提示符。

    本快速入门中的步骤假设使用的是 Windows 计算机,以及作为 Git 一部分安装的 OpenSSL。 你将使用 Git Bash 提示符发出 OpenSSL 命令,并使用 Windows 命令提示符发出其他所有命令。 如果使用的是 Linux,则可以从 Bash shell 发出所有命令。

准备开发环境

在本部分,你将准备用于生成 Azure IoT C SDK 的开发环境。 示例代码尝试在执行设备的启动序列期间预配设备。

  1. 打开 Web 浏览器,转到 Azure IoT C SDK 发布页

  2. 选择页面顶部的“标记”选项卡。

  3. 复制最新版 Azure IoT C SDK 的标记名称。

  4. 在 Windows 命令提示符下,运行以下命令以克隆最新版本的 Azure IoT 设备 SDK for C GitHub 存储库。 请将 <release-tag> 替换为在上一步骤中复制的标记,例如:lts_01_2023

    git clone -b <release-tag> https://github.com/Azure/azure-iot-sdk-c.git
    cd azure-iot-sdk-c
    git submodule update --init
    

    此操作可能需要几分钟才能完成。

  5. 操作完成后,从 azure-iot-sdk-c 目录运行以下命令:

    mkdir cmake
    cd cmake
    
  6. 代码示例使用 X.509 证书通过 X.509 身份验证提供证明。 运行以下命令,以生成特定于你的开发平台(包括设备预配客户端)的 SDK 版本。 在 cmake 目录中生成模拟设备的 Visual Studio 解决方案。

    在以下命令中指定与 -Dhsm_custom_lib 结合使用的路径时,请确保使用先前创建的 cmake 目录中的库的绝对路径。 显示的路径假设将 C SDK 克隆到了 C 驱动器的根目录中。 如果你使用了其他目录,请相应地调整路径。

    cmake -Duse_prov_client:BOOL=ON -Dhsm_custom_lib=c:/azure-iot-sdk-c/cmake/provisioning_client/samples/custom_hsm_example/Debug/custom_hsm_example.lib ..
    

提示

如果 cmake 找不到 C++ 编译器,则可能会在运行以上命令时出现生成错误。 如果出现这种情况,请尝试在 Visual Studio 命令提示符窗口中运行该命令。

  1. 生成成功后,最后的几个输出行如下所示:

    -- Building for: Visual Studio 17 2022
    -- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.22000.
    -- The C compiler identification is MSVC 19.32.31329.0
    -- The CXX compiler identification is MSVC 19.32.31329.0
    
    ...
    
    -- Configuring done
    -- Generating done
    -- Build files have been written to: C:/azure-iot-sdk-c/cmake
    

在 Windows 命令提示符下,使用以下命令克隆适用于 C# 的 Azure IoT SDK GitHub 存储库:

git clone https://github.com/Azure/azure-iot-sdk-csharp.git

在 Windows 命令提示符下,使用以下命令克隆适用于 Node.js 的 Azure IoT SDK GitHub 存储库:

git clone https://github.com/Azure/azure-iot-sdk-node.git

在 Windows 命令提示符下,使用以下命令克隆适用于 Python 的 Azure IoT 设备 SDK GitHub 存储库:

git clone -b v2 https://github.com/Azure/azure-iot-sdk-python.git --recursive

注意

本教程中使用的示例位于 azure-iot-sdk-python 存储库的 v2 分支中。 Python SDK 的 V3 可用于 beta 版。

  1. 在 Windows 命令提示符下,使用以下命令克隆适用于 Java 的 Azure IoT 示例 GitHub 存储库:

    git clone https://github.com/Azure/azure-iot-sdk-java.git --recursive
    
  2. 转到 azure-iot-sdk-java 根目录,并生成项目以下载全部所需的包。

    cd azure-iot-sdk-java
    mvn install -DskipTests=true
    

创建自签名的 X.509 设备证书

在本部分,你将使用 OpenSSL 创建自签名 X.509 证书和私钥。 此证书将上传到预配服务实例并由服务进行验证。

注意

请仅将本快速入门中通过 OpenSSL 创建的证书用于开发测试。 请不要在生产环境中使用这些证书。 这些证书将在 30 天后过期,可能包含硬编码的密码,例如 1234。 若要了解如何获取适用于生产的证书,请参阅 Azure IoT 中心文档中的如何获取 X.509 CA 证书

在 Git Bash 提示符下执行本部分所述的步骤。

  1. 在 Git Bash 提示符下,导航到要在其中创建证书的目录。

  2. 运行以下命令:

    winpty openssl req -outform PEM -x509 -sha256 -newkey rsa:4096 -keyout device-key.pem -out device-cert.pem -days 30 -extensions usr_cert -addext extendedKeyUsage=clientAuth -subj "//CN=my-x509-device"
    

    重要

    仅当需要在 Windows 平台上使用 Git 来转义字符串时,才需要为使用者名称 (//CN=my-x509-device) 提供额外的西文斜杠。

  3. 当系统要求“输入 PEM 通行短语:”时,请使用通行短语 1234

  4. 如果系统要求“验证 - 输入 PEM 通行短语:”,请再次使用通行短语 1234

    现在应在运行 openssl 命令的目录中生成公钥证书文件 (device-cert.pem) 和私钥文件 (device-key.pem)。

    证书文件的使用者公用名 (CN) 设置为 my-x509-device。 对于基于 X.509 的注册,注册 ID 设置为公用名。 注册 ID 是一个不区分大小写的字符串,包含字母数字字符和以下特殊字符:'-''.''_'':'。 最后一个字符必须是字母数字或短划线 ('-')。 公用名必须遵循此格式。 DPS 支持最大长度为 128 个字符的注册 ID;但是,在 X.509 证书中,使用者公用名的最大长度为 64 个字符。 因此,使用 X.509 证书时,注册 ID 的长度限制为 64 个字符。

  5. 证书文件采用 Base 64 编码。 若要查看证书文件的使用者公用名称 (CN) 和其他属性,请输入以下命令:

    winpty openssl x509 -in device-cert.pem -text -noout
    
    Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            77:3e:1d:e4:7e:c8:40:14:08:c6:09:75:50:9c:1a:35:6e:19:52:e2
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = my-x509-device
        Validity
            Not Before: May  5 21:41:42 2022 GMT
            Not After : Jun  4 21:41:42 2022 GMT
        Subject: CN = my-x509-device
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
                Modulus:
                    00:d2:94:37:d6:1b:f7:43:b4:21:c6:08:1a:d6:d7:
                    e6:40:44:4e:4d:24:41:6c:3e:8c:b2:2c:b0:23:29:
                    ...
                    23:6e:58:76:45:18:03:dc:2e:9d:3f:ac:a3:5c:1f:
                    9f:66:b0:05:d5:1c:fe:69:de:a9:09:13:28:c6:85:
                    0e:cd:53
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                63:C0:B5:93:BF:29:F8:57:F8:F9:26:44:70:6F:9B:A4:C7:E3:75:18
            X509v3 Authority Key Identifier:
                keyid:63:C0:B5:93:BF:29:F8:57:F8:F9:26:44:70:6F:9B:A4:C7:E3:75:18
    
            X509v3 Extended Key Usage:
                TLS Web Client Authentication
    Signature Algorithm: sha256WithRSAEncryption
         82:8a:98:f8:47:00:85:be:21:15:64:b9:22:b0:13:cc:9e:9a:
         ed:f5:93:b9:4b:57:0f:79:85:9d:89:47:69:95:65:5e:b3:b1:
         ...
         cc:b2:20:9a:b7:f2:5e:6b:81:a1:04:93:e9:2b:92:62:e0:1c:
         ac:d2:49:b9:36:d2:b0:21
    
  1. 示例代码需要一个未加密的私钥。 运行以下命令以创建未加密的私钥:

    winpty openssl rsa -in device-key.pem -out unencrypted-device-key.pem
    
  2. 出现“输入 device-key.pem 的通行短语:”提示时,请使用前面用过的同一通行短语 1234

将 Git Bash 提示符保持打开状态。 稍后在本快速入门中还需要使用它。

C# 示例代码设置为使用在受密码保护的 PKCS#12 格式文件 (certificate.pfx) 中存储的 X.509 证书。 稍后在本快速入门中,你仍需使用刚刚创建的 PEM 格式公钥证书文件 (device-cert.pem) 来创建单独的注册条目。

  1. 若要生成示例所需的 PKCS12 格式的文件,请输入以下命令:

    winpty openssl pkcs12 -inkey device-key.pem -in device-cert.pem -export -out certificate.pfx
    
  2. 出现“输入 device-key.pem 的通行短语:”提示时,请使用前面用过的同一通行短语 1234

  3. 出现“输入导出密码:”提示时,请使用密码 1234

  4. 出现“确认 - 输入导出密码:”提示时,请再次使用密码 1234

    现在应会在运行 openssl 命令的目录中生成 PKCS12 格式的证书文件 (certificate.pfx)。

  5. 将此 PKCS12 格式的证书文件复制到 X.509 设备预配示例的项目目录中。 给定的路径相对于示例存储库下载到的位置。

    cp certificate.pfx ./azure-iot-sdk-csharp/provisioning/device/samples/"Getting Started"/X509Sample
    

在本快速入门的余下部分,将不需要使用 Git Bash 提示符。 但是,建议将其保持打开状态,以便在后续步骤中遇到问题时可以检查证书。

  1. 示例代码需要一个未加密的私钥。 运行以下命令以创建未加密的私钥:

    winpty openssl rsa -in device-key.pem -out unencrypted-device-key.pem
    
  2. 出现“输入 device-key.pem 的通行短语:”提示时,请使用前面用过的同一通行短语 1234

  3. 将设备证书和未加密私钥复制到 X.509 设备预配示例的项目目录中。 给定的路径相对于 SDK 下载到的位置。

    cp device-cert.pem ./azure-iot-sdk-node/provisioning/device/samples
    cp unencrypted-device-key.pem ./azure-iot-sdk-node/provisioning/device/samples
    

在本快速入门的余下部分,将不需要使用 Git Bash 提示符。 但是,建议将其保持打开状态,以便在后续步骤中遇到问题时可以检查证书。

  1. 将设备证书和私钥复制到 X.509 设备预配示例的项目目录中。 给定的路径相对于 SDK 下载到的位置。

    cp device-cert.pem ./azure-iot-sdk-python/samples/async-hub-scenarios
    cp device-key.pem ./azure-iot-sdk-python/samples/async-hub-scenarios
    

在本快速入门的余下部分,将不需要使用 Git Bash 提示符。 但是,建议将其保持打开状态,以便在后续步骤中遇到问题时可以检查证书。

  1. Java 示例代码需要一个未加密的私钥。 运行以下命令以创建未加密的私钥:

    winpty openssl pkey -in device-key.pem -out unencrypted-device-key.pem
    
  2. 出现“输入 device-key.pem 的通行短语:”提示时,请使用前面用过的同一通行短语 1234

将 Git Bash 提示符保持打开状态。 稍后在本快速入门中还需要使用它。

创建设备注册

Azure IoT 设备预配服务支持两类注册:

本文演示要使用 IoT 中心预配的单个设备的单个注册过程。

  1. 登录到 Azure 门户,并导航到设备预配服务实例。

  2. 从导航菜单的“设置”部分选择“管理注册”。

  3. 选择“单个注册”选项卡,然后选择“添加单个注册”。

    显示“添加单个注册”选项的屏幕截图。

  4. 在“添加注册”页的“注册 + 预配”上,提供以下信息以配置注册详细信息:

    字段 说明
    证明 选择“X.509 客户端证书”作为证明类型
    X.509 证书设置 上传一个或两个证书,用于验证此注册的设备。
    预配状态 如果希望此注册用于预配其设备,请选中“启用此注册”复选框。 如果希望禁用该注册,请取消选中此框。 稍后可以更改此设置。
    重新预配策略 选择一个重新预配策略,反映希望 DPS 如何处理请求重新预配的设备。 有关详细信息,请参阅重新预配策略
  5. 选择“下一步:IoT 中心”。

  6. 在“添加注册”页的“IoT 中心”选项卡上,提供以下信息以确定注册可以预配设备的目标 IoT 中心:

    字段 说明
    目标 IoT 中心 选择一个或多个链接的 IoT 中心,或向 IoT 中心添加新链接。 若要详细了解如何将 IoT 中心链接到 DPS 实例,请参阅如何链接和管理 IoT 中心
    分配策略 如果选择了多个已链接的 IoT 中心,请选择要将设备分配到不同中心的方式。 如需详细了解分配策略,请参阅如何使用分配策略

    如果仅选择了一个已链接的 IoT 中心,建议使用均匀加权分发策略。
  7. 选择“下一步:设备设置

  8. 在“添加注册”页的“设备设置”选项卡上,提供以下信息以定义新预配设备的配置方式:

    字段 说明
    设备 ID 提供将分配给 IoT 中心中预配设备的设备 ID。 如果未提供设备 ID,将使用该注册 ID。
    IoT Edge 如果预配的设备将运行 Azure IoT Edge,请选中在预配设备上启用 IoT Edge。 如果此注册适用于未启用 IoT Edge的设备,请取消选中此框。
    设备标记 使用此文本框可提供要应用于预配设备的设备孪生的任何标记。
    所需属性 使用此文本框可提供要应用于预配设备的设备孪生的任何所需属性。

    有关详细信息,请参阅了解并在 IoT 中心内使用设备孪生

  9. 在完成时选择“下一步:查看 + 创建”。

  10. 在“审阅 + 创建”选项卡上,验证你的全部值,然后选择“创建”。

准备和运行设备预配代码

在本部分,你将更新向设备预配服务实例发送设备启动序列的示例代码。 此启动序列使得设备可被识别并分配到与 DPS 实例链接的 IoT 中心。

在本部分,你将使用 Git Bash 提示符和 Visual Studio IDE。

配置预配设备代码

在本部分中,通过设备预配服务实例信息更新示例代码。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡。

  2. 复制“ID 范围”值。

    Azure 门户上“ID 范围”的屏幕截图。

  3. 启动 Visual Studio 并打开在 azure-iot-sdk-c git 存储库根目录中创建的 cmake 目录中创建的新解决方案文件。 解决方案文件命名为 azure_iot_sdks.sln

  4. 在 Visual Studio 的解决方案资源管理器中,导航到“Provision_Samples”>“prov_dev_client_sample”>“源文件”,然后打开“prov_dev_client_sample.c”。

  5. 找到 id_scope 常量,将值替换为在步骤 2 中复制的“ID 范围”值。

    static const char* id_scope = "0ne00000A0A";
    
  6. 在同一文件中找到 main() 函数的定义。 确保 hsm_type 变量设置为 SECURE_DEVICE_TYPE_X509

    SECURE_DEVICE_TYPE hsm_type;
    //hsm_type = SECURE_DEVICE_TYPE_TPM;
    hsm_type = SECURE_DEVICE_TYPE_X509;
    //hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;
    
  7. 保存所做更改。

  8. 右键单击“prov_dev_client_sample”项目,然后选择“设为启动项目”。

配置自定义 HSM 存根代码

与实际的基于硬件的安全存储交互的细节因硬件而异。 因此,本快速入门中的模拟设备使用的证书和私钥将在自定义硬件安全模块 (HSM) 存根代码中进行硬编码。

若要更新自定义 HSM 存根代码以模拟 ID 为 my-x509-device 的设备的标识,请执行以下操作:

  1. 在 Visual Studio 的解决方案资源管理器中,导航到“Provision_Samples”>“custom_hsm_example”>“源文件”,然后打开“custom_hsm_example.c”。

  2. 使用生成设备证书 my-x509-device 时使用的公用名称更新 COMMON_NAME 字符串常量的字符串值。

    static const char* const COMMON_NAME = "my-x509-device";
    
  3. 使用先前生成的设备证书 device-cert.pem 更新 CERTIFICATE 常量字符串的字符串值。

    示例中证书文本的语法必须遵循下面的模式,其中不包含额外的空格或者由 Visual Studio 进行的分析。

    static const char* const CERTIFICATE = "-----BEGIN CERTIFICATE-----\n"
    "MIIFOjCCAyKgAwIBAgIJAPzMa6s7mj7+MA0GCSqGSIb3DQEBCwUAMCoxKDAmBgNV\n"
        ...
    "MDMwWhcNMjAxMTIyMjEzMDMwWjAqMSgwJgYDVQQDDB9BenVyZSBJb1QgSHViIENB\n"
    "-----END CERTIFICATE-----";        
    

    手动更新此字符串值可能容易出错。 若要生成正确的语法,可将以下命令复制并粘贴到 Git Bash 提示符下,然后按 ENTER。 此命令将生成 CERTIFICATE 字符串常量值的语法并将其写入到输出。

    sed -e 's/^/"/;$ !s/$/""\\n"/;$ s/$/"/' device-cert.pem
    

    复制并粘贴常量值的输出证书文本。

  4. 使用设备证书 unencrypted-device-key.pem 的未加密私钥更新 PRIVATE_KEY 常量的字符串值。

    私钥文本的语法必须遵循下面的模式,不使用额外的空格或由 Visual Studio 进行解析。

    static const char* const PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n"
    "MIIJJwIBAAKCAgEAtjvKQjIhp0EE1PoADL1rfF/W6v4vlAzOSifKSQsaPeebqg8U\n"
        ...
    "X7fi9OZ26QpnkS5QjjPTYI/wwn0J9YAwNfKSlNeXTJDfJ+KpjXBcvaLxeBQbQhij\n"
    "-----END RSA PRIVATE KEY-----";
    

    手动更新此字符串值可能容易出错。 若要生成正确的语法,可将以下命令复制并粘贴到 Git Bash 提示符下,然后按 ENTER。 此命令将生成 PRIVATE_KEY 字符串常量值的语法并将其写入到输出。

    sed -e 's/^/"/;$ !s/$/""\\n"/;$ s/$/"/' unencrypted-device-key.pem
    

    复制并粘贴常量值的输出私钥文本。

  5. 保存所做更改。

  6. 右键单击“custom_hsm__-_example”项目并选择“生成”。

    重要

    在下一部分生成解决方案的其余内容之前,必须生成 custom_hsm_example 项目。

运行示例

  1. 在 Visual Studio 菜单中,选择“调试”>“开始执行(不调试)”以运行该解决方案。 如果系统提示你是否重新生成项目,请选择“是”,以便在运行项目之前重新生成项目。

    以下输出是模拟设备 my-x509-device 成功启动并连接到预配服务的示例。 设备已分配到 IoT 中心并注册:

    Provisioning API Version: 1.8.0
    
    Registering Device
    
    Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
    Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
    
    Registration Information received from service: contoso-iot-hub-2.azure-devices.net, deviceId: my-x509-device
    Press enter key to exit:
    

在本部分,你将使用 Windows 命令提示符。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡。

  2. 复制“ID 范围”值。

    Azure 门户上“ID 范围”的屏幕截图。

  3. 在 Windows 命令提示符下切换到 X509Sample 目录。 此目录位于 .\azure-iot-sdk-csharp\provisioning\device\samples\Getting Started\X509Sample 目录中,在该目录中克隆了计算机上的示例。

  4. 输入以下命令,生成并运行 X.509 设备预配示例(将 <IDScope> 值替换为你在上一部分中复制的 ID 范围)。 证书文件将默认为 ./certificate.pfx,并将提示输入 .pfx 密码。

    dotnet run -- -s <IDScope>
    

    若要将证书和密码作为参数传递,可使用以下格式。

    注意

    运行应用程序时可以传递其他参数以更改 TransportType (-t) 和 GlobalDeviceEndpoint (-g)。

    dotnet run -- -s 0ne00000A0A -c certificate.pfx -p 1234
    
  5. 设备将连接到 DPS 并分配到 IoT 中心。 随后设备将向 IoT 中心发送遥测消息。

    Loading the certificate...
    Enter the PFX password for certificate.pfx:
    ****
    Found certificate: A33DB11B8883DEE5B1690ACFEAAB69E8E928080B CN=my-x509-device; PrivateKey: True
    Using certificate A33DB11B8883DEE5B1690ACFEAAB69E8E928080B CN=my-x509-device
    Initializing the device provisioning client...
    Initialized for registration Id my-x509-device.
    Registering with the device provisioning service...
    Registration status: Assigned.
    Device my-x509-device registered to MyExampleHub.azure-devices.net.
    Creating X509 authentication for IoT Hub...
    Testing the provisioned device with IoT Hub...
    Sending a telemetry message...
    Finished.
    

在本部分,你将使用 Windows 命令提示符。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡。

  2. 复制“ID 范围”值。

    Azure 门户上“ID 范围”的屏幕截图。

  3. 在 Windows 命令提示符下,转到示例目录,并安装示例所需的包。 显示的路径相对于 SDK 克隆到的位置。

    cd .\azure-iot-sdk-node\provisioning\device\samples
    npm install
    

    此示例使用五个环境变量,通过 DPS 对 IoT 设备进行身份验证和预配。 这些环境变量包括:

    变量名称 说明
    PROVISIONING_HOST 用于连接到 DPS 实例的终结点。 对于本快速入门,请使用全局终结点 global.azure-devices-provisioning.net
    PROVISIONING_IDSCOPE DPS 实例的 ID 范围。
    PROVISIONING_REGISTRATION_ID 设备的注册 ID。 它必须与设备证书中的使用者公用名匹配。
    CERTIFICATE_FILE 设备证书文件的路径。
    KEY_FILE 设备私钥文件的路径。
  4. 为全局设备终结点和 ID 范围添加环境变量。 将 <id-scope> 替换为在步骤 2 中复制的值。

    set PROVISIONING_HOST=global.azure-devices-provisioning.net
    set PROVISIONING_IDSCOPE=<id-scope>
    
  5. 设置设备注册 ID 的环境变量。 IoT 设备的注册 ID 必须与设备证书上的使用者公用名匹配。 如果你按照本快速入门中的步骤生成了自签名测试证书,则 my-x509-device 是设备的使用者名称和注册 ID。

    set PROVISIONING_REGISTRATION_ID=my-x509-device
    
  6. 为设备证书和(未加密的)设备私钥文件设置环境变量。

    set CERTIFICATE_FILE=.\device-cert.pem
    set KEY_FILE=.\unencrypted-device-key.pem
    
  7. 运行示例,然后验证设备是否已成功预配。

    node register_x509.js
    

    应会看到与如下示例类似的输出:

    registration succeeded
    assigned hub=contoso-hub-2.azure-devices.net
    deviceId=my-x509-device
    Client connected
    send status: MessageEnqueued
    

在本部分,你将使用 Windows 命令提示符。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡。

  2. 复制“ID 范围”和“全局设备终结点”值。

    Azure 门户上 ID 范围和全局设备终结点的屏幕截图。

  3. 在 Windows 命令提示符下,转到 provision_x509.py 示例的目录。 显示的路径相对于 SDK 克隆到的位置。

    cd ./azure-iot-sdk-python/samples/async-hub-scenarios
    

    此示例使用六个环境变量,通过 DPS 对 IoT 设备进行身份验证和预配。 这些环境变量包括:

    变量名称 说明
    PROVISIONING_HOST 用于连接到 DPS 实例的全局终结点。
    PROVISIONING_IDSCOPE DPS 实例的 ID 范围。
    DPS_X509_REGISTRATION_ID 设备的注册 ID。 它还必须与设备证书上的使用者名称相符。
    X509_CERT_FILE 设备证书文件的路径。
    X509_KEY_FILE 设备证书私钥文件的路径。
    PASS_PHRASE 用于对证书和私钥文件进行加密的密码 (1234)。
  4. 为全局设备终结点和 ID 范围添加环境变量。

    set PROVISIONING_HOST=global.azure-devices-provisioning.net
    set PROVISIONING_IDSCOPE=<ID scope for your DPS resource>
    
  5. 设置注册 ID 的环境变量。 IoT 设备的注册 ID 必须与设备证书上的使用者名称相符。 如果你按照本快速入门中的步骤生成了自签名测试证书,则 my-x509-device 是设备的使用者名称和注册 ID。

    set DPS_X509_REGISTRATION_ID=my-x509-device
    
  6. 为证书文件、私钥文件和通行短语设置环境变量。

    set X509_CERT_FILE=./device-cert.pem
    set X509_KEY_FILE=./device-key.pem
    set PASS_PHRASE=1234
    
  7. 查看 provision_x509.py 的代码。 如果未使用 Python 版本 3.7 或更高版本,请执行此处所述的代码更改以替换 asyncio.run(main()) 并保存更改。

  8. 运行该示例。 该示例将连接到 DPS,后者会将设备预配到 IoT 中心。 预配设备后,示例将向 IoT 中心发送一些测试消息。

    $ python azure-iot-sdk-python/samples/async-hub-scenarios/provision_x509.py
    RegistrationStage(RequestAndResponseOperation): Op will transition into polling after interval 2.  Setting timer.
    The complete registration result is
    my-x509-device
    TestHub12345.azure-devices.net
    initialAssignment
    null
    Will send telemetry from the provisioned device
    sending message #4
    sending message #7
    sending message #2
    sending message #8
    sending message #5
    sending message #9
    sending message #1
    sending message #6
    sending message #10
    sending message #3
    done sending message #4
    done sending message #7
    done sending message #2
    done sending message #8
    done sending message #5
    done sending message #9
    done sending message #1
    done sending message #6
    done sending message #10
    done sending message #3
    

在本部分,你将同时使用 Windows 命令提示符和 Git Bash 提示符。

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡。

  2. 复制“ID 范围”和“全局设备终结点”值。

    Azure 门户上 ID 范围和全局设备终结点的屏幕截图。

  3. 在 Windows 命令提示符下,导航到示例项目文件夹。 显示的路径相对于 SDK 克隆到的位置

    cd .\azure-iot-sdk-java\provisioning\provisioning-device-client-samples\provisioning-X509-sample
    
  4. 在示例代码中输入预配服务和 X.509 标识信息。 在预配期间,该信息在注册设备之前用于证明模拟设备。

    1. 在你偏好的编辑器中打开文件 .\src\main\java\samples\com\microsoft\azure\sdk\iot\ProvisioningX509Sample.java

    2. 使用先前复制的“ID 范围”和“预配服务全局终结点”更新以下值。

      private static final String idScope = "[Your ID scope here]";
      private static final String globalEndpoint = "[Your Provisioning Service Global Endpoint here]";
      private static final ProvisioningDeviceClientTransportProtocol PROVISIONING_DEVICE_CLIENT_TRANSPORT_PROTOCOL = ProvisioningDeviceClientTransportProtocol.HTTPS;
      
      
    3. 使用证书 device-cert.pem 的值更新 leafPublicPem 常量字符串的值。

      证书文本的语法必须遵循以下模式,其中不包含额外的空格或字符。

      private static final String leafPublicPem = "-----BEGIN CERTIFICATE-----\n" +
      "MIIFOjCCAyKgAwIBAgIJAPzMa6s7mj7+MA0GCSqGSIb3DQEBCwUAMCoxKDAmBgNV\n" +
          ...
      "MDMwWhcNMjAxMTIyMjEzMDMwWjAqMSgwJgYDVQQDDB9BenVyZSBJb1QgSHViIENB\n" +
      "-----END CERTIFICATE-----";        
      

      手动更新此字符串值可能容易出错。 若要生成正确的语法,可将以下命令复制并粘贴到 Git Bash 提示符下,然后按 ENTER。 此命令将生成 leafPublicPem 字符串常量值的语法并将其写入到输出。

      sed 's/^/"/;$ !s/$/\\n" +/;$ s/$/"/' device-cert.pem
      

      复制并粘贴常量值的输出证书文本。

    4. 使用设备证书 unencrypted-device-key.pem 的未加密私钥更新 leafPrivateKey 常量的字符串值。

      私钥文本的语法必须遵循以下模式,其中不包含额外的空格或字符。

      private static final String leafPrivateKey = "-----BEGIN PRIVATE KEY-----\n" +
      "MIIJJwIBAAKCAgEAtjvKQjIhp0EE1PoADL1rfF/W6v4vlAzOSifKSQsaPeebqg8U\n" +
          ...
      "X7fi9OZ26QpnkS5QjjPTYI/wwn0J9YAwNfKSlNeXTJDfJ+KpjXBcvaLxeBQbQhij\n" +
      "-----END PRIVATE KEY-----";
      

      手动更新此字符串值可能容易出错。 若要生成正确的语法,可将以下命令复制并粘贴到 Git Bash 提示符下,然后按 ENTER。 此命令将生成 leafPrivateKey 字符串常量值的语法并将其写入到输出。

      sed 's/^/"/;$ !s/$/\\n" +/;$ s/$/"/' unencrypted-device-key.pem
      

      复制并粘贴常量值的输出私钥文本。

    5. 保存所做更改。

  5. 生成示例,然后转到 target 文件夹。

    mvn clean install
    cd target
    
  6. 生成过程将在 target 文件夹中输出采用以下文件格式的 .jar 文件:provisioning-x509-sample-{version}-with-deps.jar;例如:provisioning-x509-sample-1.8.1-with-deps.jar。 执行该 .jar 文件。 可能需要替换以下命令中的版本。

    java -jar ./provisioning-x509-sample-1.8.1-with-deps.jar
    

    该示例将连接到 DPS,后者会将设备预配到 IoT 中心。 预配设备后,示例将向 IoT 中心发送一些测试消息。

    Starting...
    Beginning setup.
    WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
    2022-05-11 09:42:05,025 DEBUG (main) [com.microsoft.azure.sdk.iot.provisioning.device.ProvisioningDeviceClient] - Initialized a ProvisioningDeviceClient instance using SDK version 2.0.0
    2022-05-11 09:42:05,027 DEBUG (main) [com.microsoft.azure.sdk.iot.provisioning.device.ProvisioningDeviceClient] - Starting provisioning thread...
    Waiting for Provisioning Service to register
    2022-05-11 09:42:05,030 INFO (global.azure-devices-provisioning.net-6255a8ba-CxnPendingConnectionId-azure-iot-sdk-ProvisioningTask) [com.microsoft.azure.sdk.iot.provisioning.device.internal.task.ProvisioningTask] - Opening the connection to device provisioning service...
    2022-05-11 09:42:05,252 INFO (global.azure-devices-provisioning.net-6255a8ba-Cxn6255a8ba-azure-iot-sdk-ProvisioningTask) [com.microsoft.azure.sdk.iot.provisioning.device.internal.task.ProvisioningTask] - Connection to device provisioning service opened successfully, sending initial device registration message
    2022-05-11 09:42:05,286 INFO (global.azure-devices-provisioning.net-6255a8ba-Cxn6255a8ba-azure-iot-sdk-RegisterTask) [com.microsoft.azure.sdk.iot.provisioning.device.internal.task.RegisterTask] - Authenticating with device provisioning service using x509 certificates
    2022-05-11 09:42:06,083 INFO (global.azure-devices-provisioning.net-6255a8ba-Cxn6255a8ba-azure-iot-sdk-ProvisioningTask) [com.microsoft.azure.sdk.iot.provisioning.device.internal.task.ProvisioningTask] - Waiting for device provisioning service to provision this device...
    2022-05-11 09:42:06,083 INFO (global.azure-devices-provisioning.net-6255a8ba-Cxn6255a8ba-azure-iot-sdk-ProvisioningTask) [com.microsoft.azure.sdk.iot.provisioning.device.internal.task.ProvisioningTask] - Current provisioning status: ASSIGNING
    Waiting for Provisioning Service to register
    2022-05-11 09:42:15,685 INFO (global.azure-devices-provisioning.net-6255a8ba-Cxn6255a8ba-azure-iot-sdk-ProvisioningTask) [com.microsoft.azure.sdk.iot.provisioning.device.internal.task.ProvisioningTask] - Device provisioning service assigned the device successfully
    IotHUb Uri : MyExampleHub.azure-devices.net
    Device ID : java-device-01
    2022-05-11 09:42:25,057 INFO (main) [com.microsoft.azure.sdk.iot.device.transport.ExponentialBackoffWithJitter] - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
    2022-05-11 09:42:25,080 INFO (main) [com.microsoft.azure.sdk.iot.device.transport.ExponentialBackoffWithJitter] - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
    2022-05-11 09:42:25,087 DEBUG (main) [com.microsoft.azure.sdk.iot.device.DeviceClient] - Initialized a DeviceClient instance using SDK version 2.0.3
    2022-05-11 09:42:25,129 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection] - Opening MQTT connection...
    2022-05-11 09:42:25,150 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sending MQTT CONNECT packet...
    2022-05-11 09:42:25,982 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sent MQTT CONNECT packet was acknowledged
    2022-05-11 09:42:25,983 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sending MQTT SUBSCRIBE packet for topic devices/java-device-01/messages/devicebound/#
    2022-05-11 09:42:26,068 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sent MQTT SUBSCRIBE packet for topic devices/java-device-01/messages/devicebound/# was acknowledged
    2022-05-11 09:42:26,068 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection] - MQTT connection opened successfully
    2022-05-11 09:42:26,070 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - The connection to the IoT Hub has been established
    2022-05-11 09:42:26,071 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Updating transport status to new status CONNECTED with reason CONNECTION_OK
    2022-05-11 09:42:26,071 DEBUG (main) [com.microsoft.azure.sdk.iot.device.DeviceIO] - Starting worker threads
    2022-05-11 09:42:26,073 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Invoking connection status callbacks with new status details
    2022-05-11 09:42:26,074 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Client connection opened successfully
    2022-05-11 09:42:26,075 INFO (main) [com.microsoft.azure.sdk.iot.device.DeviceClient] - Device client opened successfully
    Sending message from device to IoT Hub...
    2022-05-11 09:42:26,077 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Message was queued to be sent later ( Message details: Correlation Id [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [aaaa0000-bb11-2222-33cc-444444dddddd] )
    Press any key to exit...
    2022-05-11 09:42:26,079 DEBUG (MyExampleHub.azure-devices.net-java-device-01-ee6c362d-Cxn7a1fb819-e46d-4658-9b03-ca50c88c0440-azure-iot-sdk-IotHubSendTask) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Sending message ( Message details: Correlation Id [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [aaaa0000-bb11-2222-33cc-444444dddddd] )
    2022-05-11 09:42:26,422 DEBUG (MQTT Call: java-device-01) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - IotHub message was acknowledged. Checking if there is record of sending this message ( Message details: Correlation Id [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [aaaa0000-bb11-2222-33cc-444444dddddd] )
    2022-05-11 09:42:26,425 DEBUG (MyExampleHub.azure-devices.net-java-device-01-ee6c362d-Cxn7a1fb819-e46d-4658-9b03-ca50c88c0440-azure-iot-sdk-IotHubSendTask) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Invoking the callback function for sent message, IoT Hub responded to message ( Message details: Correlation Id [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [aaaa0000-bb11-2222-33cc-444444dddddd] ) with status OK
    Message sent!
    

确认设备预配注册

若要查看设备预配到了哪个 IoT 中心,请检查先前创建的单独注册的注册详细信息:

  1. 在 Azure 门户中转到你的设备预配服务。

  2. 在“设置”菜单中,选择“管理注册” 。

  3. 选择“单个注册”。 先前创建的 X.509 注册条目 my-x509-device 应显示在列表中。

  4. 选择该注册条目。 设备分配到的 IoT 中心及其设备 ID 显示在“注册状态”下。

若要验证 IoT 中心上的设备,请执行以下操作:

  1. 在 Azure 门户中,转到设备分配到的 IoT 中心。

  2. 在“设备管理”菜单中选择“设备”。

  3. 如果设备已成功预配,则其设备 ID my-x509-device 应会显示在列表中,且“状态”设置为“已启用”。 如果未看到你的设备,请选择“刷新”。

    显示设备已注册到 Azure 门户的 IoT 中心的屏幕截图。

重要

如果从设备的注册项中的默认值更改了“初始设备孪生状态”,则它会从中心拉取所需的孪生状态,并执行相应的操作。 有关详细信息,请参阅了解并在 IoT 中心内使用设备孪生

清理资源

如果你打算继续使用和探索设备客户端示例,请不要清理在本快速入门中创建的资源。 如果你不打算继续学习,请按以下步骤删除本快速入门中创建的所有资源。

删除设备注册

  1. 关闭计算机上的设备客户端示例输出窗口。

  2. 在 Azure 门户的左侧菜单中,选择“所有资源”。

  3. 选择你的设备预配服务。

  4. 在“设置”菜单中,选择“管理注册” 。

  5. 选择“单个注册”选项卡。

  6. 选中在本快速入门中注册的设备的“注册 ID”旁边的复选框。

  7. 在页面顶部,选择“删除”。

从 IoT 中心删除设备注册

  1. 在 Azure 门户的左侧菜单中,选择“所有资源”。

  2. 选择 IoT 中心。

  3. 在“资源管理器”菜单中选择“IoT 设备” 。

  4. 选中在本快速入门中注册的设备的“设备 ID”旁边的复选框。

  5. 在页面顶部,选择“删除”。

后续步骤

在本快速入门中,你使用单个注册将单个设备预配到了 IoT 中心。 接下来了解如何跨多个中心预配多个设备。