在 ASP.NET Core 应用中使用用于 .NET 的 Azure SDK

Azure SDK for .NET 使 ASP.NET Core 应用能够与许多不同的 Azure 服务集成。 本文介绍在 ASP.NET Core 应用中采用适用于 .NET 的 Azure SDK 的最佳做法和步骤。 将了解如何执行以下操作:

  • 注册服务进行依赖项注入。
  • 在不使用密码或机密的情况下向 Azure 进行身份验证。
  • 实现集中式标准化配置。
  • 配置常见的 Web 应用问题,例如日志记录和重试。

探索常见的 Azure SDK 客户端库

ASP.NET 连接到 Azure 服务的核心应用通常取决于以下 Azure SDK 客户端库:

  • Microsoft.Extensions.Azure 提供了帮助程序方法,用于将客户端注册到依赖项注入服务集合,并处理各种问题,例如设置日志记录、处理 DI 服务生存期和身份验证凭据管理。
  • Azure.Identity 支持跨 Azure SDK Microsoft Entra ID 身份验证支持。 它提供一组 TokenCredential 实现来构造支持 Microsoft Entra 身份验证的 Azure SDK 客户端。
  • Azure.<service-namespace> 库(如 Azure.Storage.BlobsAzure.Messaging.ServiceBus)提供服务客户端和其他类型,以帮助连接和使用特定的 Azure 服务。 有关这些库的完整清单,请参阅 使用 Azure.Core 的库。

在前面的部分中,你将了解如何实现使用这些库的 ASP.NET Core 应用程序。

将 Azure SDK 客户端注册到 DI 服务集合

用于 .NET 的 Azure SDK 客户端库提供服务客户端,用于将应用连接到 Azure 服务,例如Azure Blob 存储和 Azure 密钥库。 将这些服务注册到应用的文件中的依赖项容器 Program.cs ,以便通过 依赖项注入提供这些服务。

完成以下步骤以注册所需的服务:

  1. 添加 Microsoft.Extensions.Azure 包:

    dotnet add package Microsoft.Extensions.Azure
    
  2. 添加相关的 Azure.* 服务客户端包:

    dotnet add package Azure.Security.KeyVault.Secrets
    dotnet add package Azure.Storage.Blobs
    dotnet add package Azure.Messaging.ServiceBus
    
  3. Program.cs应用的文件中,从Microsoft.Extensions.Azure库中调用AddAzureClients扩展方法,注册客户端以与每个 Azure 服务通信。 某些客户端库为 Azure 服务功能的特定子组提供其他 子组 。 可以通过扩展方法注册此类子实体进行依赖项注入 AddClient

    builder.Services.AddAzureClients(clientBuilder =>
    {
        // Register a client for each Azure service using inline configuration
        clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
        clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
        clientBuilder.AddServiceBusClientWithNamespace(
            "<your_namespace>.servicebus.windows.net");
    
        // Register a subclient for each Azure Service Bus Queue
        var queueNames = new string[] { "queue1", "queue2" };
        foreach (string queue in queueNames)
        {
            clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
                (_, _, provider) => provider.GetService<ServiceBusClient>()
                        .CreateSender(queue)).WithName(queue);
        }
    
        // Register a shared credential for Microsoft Entra ID authentication
        clientBuilder.UseCredential(new DefaultAzureCredential());
    });
    
  4. 将已注册的客户端注入 ASP.NET 核心应用组件、服务或 API 终结点:

    app.MapGet("/reports", async (
            BlobServiceClient blobServiceClient,
            IAzureClientFactory<ServiceBusSender> senderFactory) =>
    {
        // Create the named client
        ServiceBusSender serviceBusSender = senderFactory.CreateClient("queue1");
    
        await serviceBusSender.SendMessageAsync(new ServiceBusMessage("Hello world"));
    
        // Use the blob client
        BlobContainerClient containerClient
            = blobServiceClient.GetBlobContainerClient("reports");
    
        List<BlobItem> reports = new();
        await foreach (BlobItem blobItem in containerClient.GetBlobsAsync())
        {
            reports.Add(blobItem);
        }
    
        return reports;
    })
    .WithName("GetReports");
    

有关详细信息,请参阅 Azure SDK for .NET 的依赖项注入。

使用 Microsoft Entra ID 进行身份验证

使用 Microsoft Entra ID 进行基于令牌的身份验证是对 Azure 服务的请求进行身份验证的建议方法。 为了授权这些请求, Azure 基于角色的访问控制 (RBAC) 基于用户的 Microsoft Entra 标识和分配的角色管理对 Azure 资源的访问。

Azure 标识 库用于上述基于令牌的身份验证支持。 该库提供类,例如 DefaultAzureCredential 简化配置安全连接的过程。 DefaultAzureCredential 支持多种身份验证方法,并确定应在运行时使用哪种方法。 通过这种方法,你的应用可在不同环境(本地与生产)中使用不同的身份验证方法,而无需实现特定于环境的代码。 有关这些主题的更多详细信息,请访问 Azure SDK for .NET 文档的“身份验证”部分。

注意

许多 Azure 服务还允许使用密钥授权请求。 但是,应谨慎使用此方法。 开发人员必须尽量避免在不安全的位置公开访问密钥。 拥有访问密钥的任何人都可以授权针对关联的 Azure 资源的请求。

  1. 添加 Azure.Identity 包:

    dotnet add package Azure.Identity
    
  2. Program.cs应用的文件中,从Microsoft.Extensions.Azure库调用UseCredential扩展方法,为所有已注册的 Azure 服务客户端设置共享DefaultAzureCredential实例:

    builder.Services.AddAzureClients(clientBuilder =>
    {
        // Register a client for each Azure service using inline configuration
        clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
        clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
        clientBuilder.AddServiceBusClientWithNamespace(
            "<your_namespace>.servicebus.windows.net");
    
        // Register a subclient for each Azure Service Bus Queue
        var queueNames = new string[] { "queue1", "queue2" };
        foreach (string queue in queueNames)
        {
            clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
                (_, _, provider) => provider.GetService<ServiceBusClient>()
                        .CreateSender(queue)).WithName(queue);
        }
    
        // Register a shared credential for Microsoft Entra ID authentication
        clientBuilder.UseCredential(new DefaultAzureCredential());
    });
    

    DefaultAzureCredential 发现当前环境中的可用凭据,并使用它们向 Azure 服务进行身份验证。 有关扫描凭据的顺序和位置 DefaultAzureCredential ,请参阅 DefaultAzureCredential 概述。 使用共享 DefaultAzureCredential 实例可确保使用基础令牌缓存,从而提高应用程序复原能力和性能,因为对新令牌的请求更少。

应用配置

Azure SDK 服务客户端支持配置以更改其默认行为。 可通过两种方式配置服务客户端:

  • JSON 配置文件 通常是推荐的方法,因为它们简化了在环境之间的应用部署方面的管理差异。
  • 注册服务客户端时,可以应用内联代码配置。 例如,在 “注册客户端和子客户端 ”部分中,显式将 URI 变量传递给客户端构造函数。

IConfiguration 优先规则受 Microsoft.Extensions.Azure 扩展方法的尊重,这些方法在 配置提供程序 文档中进行了详细介绍。

完成以下部分中的步骤,将应用更新为针对相应环境使用 JSON 文件配置。 使用 appsettings.Development.json 该文件进行开发设置,将 appsettings.Production.json 文件用于生产环境设置。 可以将名称为类上的 ClientOptions 公共属性的配置设置添加到 JSON 文件。

配置已注册的服务

  1. appsettings.<environment>.json使用突出显示的服务配置更新应用中的文件:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning",
          "Azure.Messaging.ServiceBus": "Debug"
        }
      },
      "AzureDefaults": {
        "Diagnostics": {
          "IsTelemetryDisabled": false,
          "IsLoggingContentEnabled": true
        },
        "Retry": {
          "MaxRetries": 3,
          "Mode": "Exponential"
        }
      },
      "KeyVault": {
        "VaultUri": "https://<your-key-vault-name>.vault.azure.net"
      },
      "ServiceBus": {
        "Namespace": "<your_service-bus_namespace>.servicebus.windows.net"
      },
      "Storage": {
        "ServiceUri": "https://<your-storage-account-name>.storage.windows.net"
      }
    }
    

    在前面的 JSON 示例中:

  2. Program.cs更新该文件以检索 JSON IConfiguration 文件配置,并将其传递到服务注册中:

    builder.Services.AddAzureClients(clientBuilder =>
    {
        // Register clients using a config file section
        clientBuilder.AddSecretClient(
            builder.Configuration.GetSection("KeyVault"));
    
        clientBuilder.AddBlobServiceClient(
            builder.Configuration.GetSection("Storage"));
    
        // Register clients using a specific config key-value pair
        clientBuilder.AddServiceBusClientWithNamespace(
            builder.Configuration["ServiceBus:Namespace"]);
    

配置 Azure 默认值和重试

你可能想要全局更改默认的 Azure 客户端配置或特定服务客户端。 例如,你可能需要不同的重试设置或使用不同的服务 API 版本。 你可以全局设置或按服务设置重试设置。

  1. 更新配置文件以设置默认 Azure 设置,例如所有已注册的 Azure 客户端都将使用的新默认重试策略:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning",
          "Azure.Messaging.ServiceBus": "Debug"
        }
      },
      "AzureDefaults": {
        "Diagnostics": {
          "IsTelemetryDisabled": false,
          "IsLoggingContentEnabled": true
        },
        "Retry": {
          "MaxRetries": 3,
          "Mode": "Exponential"
        }
      },
      "KeyVault": {
        "VaultUri": "https://<your-key-vault-name>.vault.azure.net"
      },
      "ServiceBus": {
        "Namespace": "<your_service-bus_namespace>.servicebus.windows.net"
      },
      "Storage": {
        "ServiceUri": "https://<your-storage-account-name>.storage.windows.net"
      }
    }
    
  2. Program.cs 文件中,调用 ConfigureDefaults 扩展方法以检索默认设置并将其应用于服务客户端:

    builder.Services.AddAzureClients(clientBuilder =>
    {
        // Register clients using a config file section
        clientBuilder.AddSecretClient(
            builder.Configuration.GetSection("KeyVault"));
    
        clientBuilder.AddBlobServiceClient(
            builder.Configuration.GetSection("Storage"));
    
        // Register clients using a specific config key-value pair
        clientBuilder.AddServiceBusClientWithNamespace(
            builder.Configuration["ServiceBus:Namespace"]);
    
        // Register a subclient for each Azure Service Bus Queue
        string[] queueNames = [ "queue1", "queue2" ];
        foreach (string queue in queueNames)
        {
            clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
                (_, _, provider) => provider.GetService<ServiceBusClient>()
                        .CreateSender(queue)).WithName(queue);
        }
    
        clientBuilder.UseCredential(new DefaultAzureCredential());
    
        // Set up any default settings
        clientBuilder.ConfigureDefaults(
            builder.Configuration.GetSection("AzureDefaults"));
    });
    

配置日志记录

用于 .NET 的 Azure SDK 客户端库可以记录客户端库操作,以监视对 Azure 服务的请求和响应。 客户端库还可以记录各种其他事件,包括重试、令牌检索以及来自各种客户端的服务特定事件。 使用 AddAzureClients 扩展方法注册 Azure SDK 客户端时,会 AzureEventSourceLogForwarder 向依赖项注入容器注册该客户端。 转发 AzureEventSourceLogForwarder 来自 Azure SDK 事件源的 ILoggerFactory 日志消息,以便使用标准 ASP.NET 核心日志记录配置进行日志记录。

下表描述了用于 .NET 的 Azure SDK EventLevel 如何映射到 ASP.NET Core LogLevel。 有关这些主题和其他方案的详细信息,请参阅 使用用于 .NET 的 Azure SDK 和 用于 .NET 的 Azure SDK 进行依赖项注入的日志记录。

Azure SDK EventLevel ASP.NET Core LogLevel
Critical Critical
Error Error
Informational Information
Warning Warning
Verbose Debug
LogAlways Information

可以使用“配置身份验证”部分中概述的相同 JSON 配置更改默认日志级别和其他设置。 例如,通过将密钥设置为以下项,Logging:LogLevel:Azure.Messaging.ServiceBus将日志级别切换ServiceBusClientDebug

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Azure.Messaging.ServiceBus": "Debug"
    }
  },
  "AzureDefaults": {
    "Diagnostics": {
      "IsTelemetryDisabled": false,
      "IsLoggingContentEnabled": true
    },
    "Retry": {
      "MaxRetries": 3,
      "Mode": "Exponential"
    }
  },
  "KeyVault": {
    "VaultUri": "https://<your-key-vault-name>.vault.azure.net"
  },
  "ServiceBus": {
    "Namespace": "<your_service-bus_namespace>.servicebus.windows.net"
  },
  "Storage": {
    "ServiceUri": "https://<your-storage-account-name>.storage.windows.net"
  }
}