使用自签发X509证书认证并连接设备
分类: Azure物联网 ◆ 标签: #Azure #IoT Hub # #入门 #指南 ◆ 发布于: 2023-06-13 21:56:43

我们之前的文章已经演示了如何通过SAS Key
连接Azure IoT Hub
, 我们本节演示如何通过自签发证书认证并连接设备。
请先满足我们的前提条件:
- 一个
Azure
账号 - 创建好一个
Azure IoT Hub
的资源
我们先准备自签发证书。
需要注意的是自签发证书认证,也称之为指纹认证(thumbprint)
,因为我们将自签发的证书指纹填充到设备配置上,然后在认证连接时,设备读取存在本地的证书,并建立连接。
准备自签发证书
如果是使用Windows
请启用WSL
, 安装ubuntu和openssl, 我们使用如下的脚本准备自签发证书, 另外需要注意的是每个设备上用于填充指纹的位置有两个,所以我们需要两个自签发证书。
自签发证书1
openssl genpkey -out device1.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
创建CSR
:
openssl req -new -key device1.key -out device1.csr Country Name (2 letter code) [XX]:. State or Province Name (full name) []:. Locality Name (eg, city) [Default City]:. Organization Name (eg, company) [Default Company Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (eg, your name or your server hostname) []:testdevice2 Email Address []:
注意输入.
表示使用默认值,我们需要在字段Common Name (eg, your name or your server hostname) []
这里天上我们设备的ID
, 假设我们这里使用testdevice2
作为设备ID
。
检查CSR
和自签发证书:
openssl req -text -in device1.csr -noout
openssl x509 -req -days 365 -in device1.csr -signkey device1.key -out device1.crt
使用上述同样的步骤创建自签发证书2:
openssl genpkey -out device2.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048
openssl req -new -key device2.key -out device2.csr
openssl x509 -req -days 365 -in device2.csr -signkey device2.key -out device2.crt
在创建完成两个自签发证书之后,使用如下的方法取得指纹thumbprint
:
openssl x509 -in device1.crt -noout -fingerprint openssl x509 -in device2.crt -noout -fingerprint
由于设备SDK
的证书需要使用pfx
格式,使用如下的命令转换:
openssl pkcs12 -export -in device1.crt -inkey device1.key -out device1.pfx openssl pkcs12 -export -in device2.crt -inkey device2.key -out device2.pfx
注意自签发证书指纹返回的格式是这样的:
SHA1 Fingerprint=XX:XX:XX:XX:XX:XX:XX:XX:XX:D9:1F:13:F9:4E:D0:F4:98:3E:C3:6C
两个自签发证书返回都是这样格式的, 我们只需要取Fingerprint=
之后的字符串,并将所有的:
去掉。
两个指纹都应该这样操作,并保存下来。
注意
本节的代码可以从:https://github.com/hylinux/azure-iot-hub-examples/tree/main/DeviceConnectBySelfSignX509 下载。
创建设备
登录到Azure Portal
, 并创建设备,如下图:
- 1处填写设备ID, 注意必须是
testdevice2
, 大小写都需要一致,因为我们之前在证书里填写了设备ID
- 2处先择`X.509 Self-Signed'的认证方式
- 3处填写第一个自签发证书的指纹,刚刚我们已经拿到的
- 4处填写另外一个自签发证书的指纹。
填写好之后创建设备。
创建设备应用
我们接下来创建设备的引用:
dotnet new console -o DeviceConnectBySelfSignX509
cd .\DeviceConnectBySelfSignX509\
dotnet add package Microsoft.Extensions.Hosting
dotnet add package Microsoft.Azure.Devices.Client
mkdir X509
将之前创建好的pfx
证书拷贝到目录X509
里。需要注意的时,同一时间只能使用一个证书。
我们在本项目中仍然使用Secret Manager
来管理必要的机密信息:
dotnet user-secrets init dotnet user-secrets set "Device:IoTHubHostURL" "<你IoT Hub服务器的网址>" dotnet user-secrets set "X509:Password" "<你证书的密码>" dotnet user-secrets set "Device:Id" "testdevice2"
打开文件Program.cs
,添加如下的内容:
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Azure.Devices.Client; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.Json; using IHost host = Host.CreateDefaultBuilder(args).Build(); var iotHubHostURL = host.Services.GetRequiredService<IConfiguration>().GetValue<string>("Device:IoTHubHostURL"); var certPassword = host.Services.GetRequiredService<IConfiguration>().GetValue<string>("X509:Password"); var deviceId = host.Services.GetRequiredService<IConfiguration>().GetValue<string>("Device:Id"); var cert = new X509Certificate2(@"D:\MyProjects\azure-iot-hub-examples\DeviceConnectBySelfSignX509\X509\device.pfx", certPassword); var auth = new DeviceAuthenticationWithX509Certificate(deviceId, cert); var deviceClient = DeviceClient.Create(iotHubHostURL, auth, TransportType.Mqtt); Console.WriteLine("设备连接正常。"); await host.RunAsync();
从上述代码中可以看出要使用自签发证书主要这三行代码在起作用:
var cert = new X509Certificate2(@"D:\MyProjects\azure-iot-hub-examples\DeviceConnectBySelfSignX509\X509\device.pfx", certPassword); var auth = new DeviceAuthenticationWithX509Certificate(deviceId, cert); var deviceClient = DeviceClient.Create(iotHubHostURL, auth, TransportType.Mqtt);
在底部加上方法SendDeviceToCloudMessagesAsync
的定义,并在Console.WriteLine("设备连接正常。");
后面加上以下两行:
using var cts = new CancellationTokenSource(); await SendDeviceToCloudMessagesAsync(deviceClient, cts.Token);
运行应用:
$env:DOTNET_ENVIRONMENT = "Development" dotnet run
即可以观察连接的结果。