C# IoT 设备 SDK、IotHubUnauthorizedAccess 仅在使用 X.509 证书 GetFileUploadSasUriAsync 时

问题描述 投票:0回答:1

我正在整理一个物联网测试工具作为我们公司的内部参考。

我可以在 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
c# azure iot azure-iot-hub
1个回答
0
投票

您遇到的错误消息“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.");
                }
            }
        }

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.