我正在整理一个物联网测试工具作为我们公司的内部参考。
我可以在 SymmetricKey 和 X509 证书之间切换,使用 DPS 进行配置并针对我们感兴趣的端点运行测试。
当我测试文件上传功能时,使用 SymmetricKey 时,我可以请求文件并将其发布到存储帐户。使用完全相同的方法,使用 X509 cert 作为身份验证方法,我遇到了以下问题。
当使用 X509 使用相同的“DeviceClient”实例时,我可以发送数据、更新和调用双胞胎、发送 C2D 消息和调用方法。只有 GetFileUploadSasUriAsync 遇到这个问题,我被难住了。
产生错误的行:
“FileUploadSasUriResponse sasUri =等待 _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, CancellationToken.None);"
我做错了什么?
代码
初始化IoTClient
var certPath = AppDomain.CurrentDomain.BaseDirectory + storedConfig.CertName;
Console.WriteLine($"Loading the certificate...");
using X509Certificate2 certificate = new X509Certificate2(certPath, storedConfig.CertPassword);
using var security = new SecurityProviderX509Certificate(certificate);
using var auth = new DeviceAuthenticationWithX509Certificate(storedConfig.DeviceName, certificate);
IoTDeviceClient = DeviceClient.Create(storedConfig.AssignedIoTHub, auth, TransportType.Mqtt);
IoTDeviceClient.SetRetryPolicy(new ExponentialBackoff(5, new TimeSpan(0, 1, 30), new TimeSpan(0, 1, 30), new TimeSpan(0, 1, 15)));
IoTDeviceClient.OpenAsync().Wait();
文件操作类
public class FileOperations
{
readonly DeviceClient _deviceClient;
public static LocalConfigStore ConfigStore = new LocalConfigStore();
/// <summary>
/// Load the client and start listening for file upload notifications
/// </summary>
internal FileOperations()
{
_deviceClient = Program.IoTDeviceClient;
ReceiveFileUploadNotificationAsync();
}
/// <summary>
/// This method is used to upload a file to the IoT Hub
/// </summary>
public async void UploadFile()
{
// Generate a large file to upload
var commonOps = new Utils.Common();
var testFilePath = commonOps.GenerateLargeFile();
// Create stream
using var fileStreamSource = new FileStream(testFilePath, FileMode.Open);
var fileName = Path.GetFileName(testFilePath);
var fileUploadTime = Stopwatch.StartNew();
// Get the SAS URI for the file upload
var fileUploadSasUriRequest = new FileUploadSasUriRequest
{
BlobName = fileName
};
FileUploadSasUriResponse sasUri = await _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, CancellationToken.None);
Uri uploadUri = sasUri.GetBlobUri();
Console.WriteLine($"Uploading file {fileName} to {uploadUri}.");
// Upload the file to blob storage
var blockBlobClient = new BlockBlobClient(uploadUri);
await blockBlobClient.UploadAsync(fileStreamSource, new BlobUploadOptions());
// Notify IoT Hub that the file upload is complete
var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
{
// Mandatory. Must be the same value as the correlation id returned in the sas uri response
CorrelationId = sasUri.CorrelationId,
// Mandatory. Will be present when service client receives this file upload notification
IsSuccess = true,
// Optional, user defined status code. Will be present when service client receives this file upload notification
StatusCode = 200,
// Optional, user-defined status description. Will be present when service client receives this file upload notification
StatusDescription = "Success"
};
// Notify IoT Hub that the file upload is complete
await _deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);
fileUploadTime.Stop();
Console.WriteLine($"File upload completed successfully.");
Console.WriteLine($"Time to upload file: {fileUploadTime.Elapsed}.");
Console.WriteLine($"Deleting Test File.");
fileStreamSource.Dispose();
File.Delete(testFilePath);
Console.WriteLine("press enter to continue.");
}
/// <summary>
/// This method is used to receive file upload notifications
/// </summary>
private async void ReceiveFileUploadNotificationAsync()
{
var connectionString = ConfigurationManager.AppSettings["ConnectionStringIotHubOwner"];
// Create service client to receive file upload notifications
ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(connectionString);
// Get file upload notification receiver
var notificationReceiver = serviceClient.GetFileNotificationReceiver();
Console.WriteLine("\nReceiving file upload notification from service");
while (true)
{
// Wait for file upload notification
var fileUploadNotification = await notificationReceiver.ReceiveAsync();
if (fileUploadNotification == null) continue;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Received file upload notification: {0}", string.Join(", ", fileUploadNotification.BlobName));
Console.ResetColor();
await notificationReceiver.CompleteAsync(fileUploadNotification);
}
}
}
错误
{"Message":"ErrorCode:IotHubUnauthorizedAccess;Unauthorized","ExceptionMessage":"Tracking ID:2d210xxxxxxxxe3afdc-G:0-TimeStamp:08/04/2023 15:48:25"}
at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.<ExecuteAsync>d__22.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Devices.Client.Transport.HttpClientHelper.<PostAsync>d__18`2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Devices.Client.Transport.HttpTransportHandler.<GetFileUploadSasUriAsync>d__15.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at RemoteIoTDeviceConsoleApp.Class.Data.FileOperations.<UploadFile>d__3.MoveNext() in E:\zzzz\xxxx\xxx\xxx\Class\Data\FileOperations.cs:line 53
您遇到的错误消息“ErrorCode:IotHubUnauthorizedAccess;Unauthorized”表示尝试使用 X.509 证书身份验证从设备访问 IoT 中心服务时出现授权问题。为您提供使用 X509 在 IoT 中心上传文件的示例使用 GetFileUploadSasUriAsync 进行证书。
var cert = new X509Certificate2("C:\\Tools\\cert\\MyCert.cer");
var auth = new DeviceAuthenticationWithX509Certificate("mydevice", cert);
var DClnt = DeviceClient.Create("HostName", auth);
private const string CertificateThumbprint = "E9DB5307C576E23009";
private const string IotHubHostName = "sampath.azure-devices.net";
private const string DeviceId = "fa";
private const string FilePath = "C:/Users/Hello.js";
static async Task Main(string[] args)
{
try
{
var auth = new DeviceAuthenticationWithX509Certificate(DeviceId, GetCertificateByThumbprint(CertificateThumbprint));
var deviceClient = DeviceClient.Create(IotHubHostName, auth, TransportType.Http1);
await SendToBlobSample(deviceClient);
}
catch (Exception ex)
{
Console.WriteLine("{0}\n", ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine(ex.InnerException.Message + "\n");
}
}
}
static async Task SendToBlobSample(DeviceClient deviceClient)
{
var fileStreamSource = new FileStream(FilePath, FileMode.Open);
var fileName = Path.GetFileName(FilePath);
Console.WriteLine("Uploading File: {0}", fileName);
var watch = System.Diagnostics.Stopwatch.StartNew();
var fileUploadSasUriRequest = new FileUploadSasUriRequest
{
BlobName = fileName
};
FileUploadSasUriResponse sasUri = await deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest);
Uri uploadUri = sasUri.GetBlobUri();
var blockBlobClient = new BlockBlobClient(uploadUri);
await blockBlobClient.UploadAsync(fileStreamSource, new BlobUploadOptions());
watch.Stop();
Console.WriteLine("Time to upload file: {0}ms\n", watch.ElapsedMilliseconds);
Console.WriteLine("File uploaded to Azure Blob Storage: {0}", fileName);
var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
{
CorrelationId = sasUri.CorrelationId,
IsSuccess = true,
StatusCode = 200,
StatusDescription = "Success"
};
await deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);
}
static X509Certificate2 GetCertificateByThumbprint(string thumbprint)
{
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (certificates.Count > 0)
{
return certificates[0];
}
else
{
throw new Exception("Certificate not found.");
}
}
}