如何使用 .NET Azure SDK 对访问 Azure 服务的 .NET 应用进行身份验证

当某个应用程序需要访问 Azure 资源(例如存储、密钥保管库或认知服务)时,该应用程序必须向 Azure 进行身份验证。 这适用于所有应用程序,不管它们是部署到 Azure、部署在本地,还是仍在本地开发人员工作站上处于开发中状态。 本文介绍使用 Azure SDK for .NET 对访问 Azure 的应用进行身份验证的建议方法。

建议应用在向 Azure 资源进行身份验证时使用基于令牌的身份验证,而不要使用连接字符串。 Azure SDK for .NET 提供支持基于令牌的身份验证的类,并允许应用无缝地向 Azure 资源进行身份验证,不管该应用是处于本地开发中状态、已部署到 Azure,还是已部署到本地服务器。

由应用用来向 Azure 资源进行身份验证的特定基于令牌的身份验证类型取决于该应用的运行位置,如下图所示。

该图显示应用的建议基于令牌的身份验证策略取决于其运行位置。

  • 当开发人员在本地开发期间运行应用时 - 该应用可以使用用于本地开发的应用程序服务主体或使用开发人员的 Azure 凭据向 Azure 进行身份验证。 在本地开发期间进行身份验证部分更详细地介绍了其中的每个选项。
  • 当应用托管在 Azure 上时 - 该应用应该使用托管标识向 Azure 资源进行身份验证。 下面的在服务器环境中进行身份验证部分更详细地介绍了此选项。
  • 当应用托管并部署在本地时 - 该应用应该使用应用程序服务主体向 Azure 资源进行身份验证。 下面的在服务器环境中进行身份验证部分更详细地介绍了此选项。

DefaultAzureCredential

借助 Azure SDK 提供的 DefaultAzureCredential 类,应用可以根据其运行所在的环境使用不同的身份验证方法。 这样,就可以将应用从本地开发环境提升到测试环境,再提升到生产环境,而无需更改代码。 为每个环境配置适当的身份验证方法,DefaultAzureCredential 将自动检测并使用该身份验证方法。 应优先使用 DefaultAzureCredential(而不是手动编写条件逻辑或功能标志的代码)在不同的环境中使用不同的身份验证方法。

本文稍后的在应用程序中使用 DefaultAzureCredential 部分详细介绍了如何使用 DefaultAzureCredential 类。

基于令牌的身份验证的优势

构建适用于 Azure 的应用时,强烈建议使用基于令牌的身份验证,而不要使用连接字符串。 与使用连接字符串进行身份验证相比,基于令牌的身份验证具有以下优势。

  • 使用下面所述的基于令牌的身份验证方法,可以建立应用在 Azure 资源上所需的特定权限。 此方法遵循最低特权原则。 相比之下,连接字符串授予对 Azure 资源的完全权限。
  • 拥有连接字符串的任何人或任何应用都可以连接到 Azure 资源,而基于令牌的身份验证方法会将资源访问权限的范围限定为需要访问该资源的应用。
  • 如果使用托管标识,则不需要存储应用程序机密。 这可以使应用变得更安全,因为不存在连接字符串或应用程序机密泄密的风险。
  • Azure SDK 中的 Azure.Identity 包在幕后为你管理令牌。 因此,使用基于令牌的身份验证与使用连接字符串一样简单。

应该仅限不访问生产数据或敏感数据的初始概念证明应用或开发原型使用连接字符串。 否则,在向 Azure 资源进行身份验证时,应始终优先使用 Azure SDK 中提供的基于令牌的身份验证类。

在服务器环境中进行身份验证

将应用程序托管在服务器环境中时,应在运行应用程序的每个环境中为每个应用程序分配唯一的应用程序标识。 在 Azure 中,应用标识由服务主体表示,这是一种特殊类型的安全主体,旨在标识该应用以及在 Azure 中对其进行身份验证。 要为应用使用的服务主体类型取决于应用的运行位置。

身份验证方法 说明
Azure 中托管的应用 Azure 中托管的应用应该使用托管标识服务主体。 托管标识旨在表示 Azure 中托管的应用的标识,并且只能用于 Azure 托管的应用。

例如,将为托管在 Azure 应用服务中的 .NET Web 应用分配一个托管标识。 然后,分配给该应用的托管标识用于对访问其他 Azure 服务的应用进行身份验证。

托管在 Azure 外部的应用
(例如本地应用)
托管在 Azure 外部的且需要连接到 Azure 服务的应用(例如本地应用)应使用应用程序服务主体。 应用程序服务主体表示 Azure 中的应用的标识,它是通过应用程序注册过程创建的。

例如,假设某个使用 Azure Blob 存储的 .NET Web 应用托管在本地。 你将使用应用注册过程为该应用创建应用程序服务主体。 AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_CLIENT_SECRET 都将存储为环境变量以供应用程序在运行时读取,并使应用能够使用应用程序服务主体向 Azure 进行身份验证。

在本地开发期间进行身份验证

在本地开发期间,当应用程序在开发人员的工作站上运行时,它仍然必须向应用使用的任何 Azure 服务进行身份验证。 本地开发期间对访问 Azure 的应用进行身份验证的两种主要策略是:

身份验证方法 说明
创建要在本地开发期间使用的专用应用程序服务主体对象 使用此方法时,专用应用程序服务主体对象是使用应用注册过程设置的,将在本地开发期间使用。 然后,服务主体的标识将存储为环境变量,供应用在本地开发中运行时访问。

使用此方法可将应用所需的特定资源权限分配给开发人员在本地开发期间使用的服务主体对象。 这可以确保应用程序只能访问它需要的特定资源,并复制应用在生产环境中拥有的权限。

此方法的缺点是需要为开发应用程序的每个开发人员创建单独的服务主体对象。

在本地开发期间使用开发人员的凭据对访问 Azure 的应用进行身份验证 使用此方法时,开发人员必须在其本地工作站上从 Visual Studio、VS Code 的 Azure Tools 扩展、Azure CLI 或 Azure PowerShell 登录到 Azure。 然后,应用程序可以访问凭据存储中的开发人员凭据,并使用这些凭据从应用访问 Azure 资源。

此方法的优点是设置更简单,因为开发人员只需从 Visual Studio、VS Code 或 Azure CLI 登录到其 Azure 帐户。 此方法的缺点是,开发人员帐户拥有的权限可能比应用程序所需的权限更多。 因此,此方法不会准确复制应用在生产环境中运行时使用的权限。

在应用程序中使用 DefaultAzureCredential

DefaultAzureCredential 支持多种身份验证方法,并确定在运行时使用的身份验证方法。 这样,应用便可以在不同的环境中使用不同的身份验证方法,而无需实现特定于环境的代码。

DefaultAzureCredential 按哪种顺序和在哪个位置查找凭据见于 DefaultAzureCredential

若要实现 DefaultAzureCredential,首先请将 Azure.Identity 和可选的 Microsoft.Extensions.Azure 包添加到应用程序。 可以使用命令行或 NuGet 包管理器来执行此操作。

在应用程序项目目录中打开所选的终端环境,然后输入以下命令。

dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure

通常会使用 SDK 中的相应客户端类来访问 Azure 服务。 应在 Program.cs 文件中注册这些类和你自己的自定义服务,以便可以在整个应用中通过依赖项注入来访问它们。 在 Program.cs 中,按照以下步骤正确设置服务和 DefaultAzureCredential

  1. 使用 using 语句包含 Azure.IdentityMicrosoft.Extensions.Azure 命名空间。
  2. 使用相关的帮助器方法注册 Azure 服务。
  3. DefaultAzureCredential 对象的实例传递给 UseCredential 方法。

以下代码片段中显示了此操作的示例。

using Microsoft.Extensions.Azure;
using Azure.Identity;

// Inside of Program.cs
builder.Services.AddAzureClients(x =>
{
    x.AddBlobServiceClient(new Uri("https://<account-name>.blob.core.windows.net"));
    x.UseCredential(new DefaultAzureCredential());
});

或者,也可以在服务中更直接地使用 DefaultAzureCredential,而无需借助其他 Azure 注册方法,如下所示。

using Azure.Identity;

// Inside of Program.cs
builder.Services.AddSingleton<BlobServiceClient>(x => 
    new BlobServiceClient(
        new Uri("https://<account-name>.blob.core.windows.net"),
        new DefaultAzureCredential()));

在本地开发期间,当上述代码在本地工作站上运行时,它将在环境变量中查找应用程序服务主体,或者在 Visual Studio、VS Code、Azure CLI 或 Azure PowerShell 中查找一组开发人员凭据,在本地开发期间,可以使用该服务主体或这些凭据对访问 Azure 资源的应用进行身份验证。

部署到 Azure 时,此代码也可以对访问 Azure 资源的应用进行身份验证。 DefaultAzureCredential 可以检索环境设置和托管标识配置,以自动向其他服务进行身份验证。

了解 DefaultAzureCredential 身份验证方法的顺序

在内部,DefaultAzureCredential 实现凭据提供程序链,以便对访问 Azure 资源的应用程序进行身份验证。 每个凭据提供程序能够检测是否为应用配置了这种类型的凭据。 DefaultAzureCredential 按顺序检查每个提供程序,并使用第一个配置了凭据的提供程序的凭据。

DefaultAzureCredential 按哪种顺序和在哪个位置查找凭据见于 DefaultAzureCredential

凭据类型 说明
应用程序服务主体 DefaultAzureCredential 读取一组环境变量,以确定是否为应用设置了应用服务主体(应用程序用户)。 如果是,则 DefaultAzureCredential 将使用这些值对访问 Azure 的应用进行身份验证。

此方法最常用于服务器环境,但也可以在进行本地开发时使用。
托管标识 如果应用程序已部署到启用了托管标识的 Azure 主机,则 DefaultAzureCredential 将使用该托管标识对访问 Azure 的应用进行身份验证。 本文档的在服务器环境中进行身份验证部分介绍了如何使用托管标识进行身份验证。

仅当使用 Azure 应用服务、Azure Functions 或 Azure 虚拟机等服务在 Azure 中托管应用程序时,此方法才适用。
Visual Studio 如果开发人员已通过登录到 Visual Studio 向 Azure 进行身份验证,则 DefaultAzureCredential 将使用同一帐户对访问 Azure 的应用进行身份验证。
Visual Studio Code 如果开发人员已使用 Visual Studio Code Azure 帐户插件向 Azure 进行身份验证,则 DefaultAzureCredential 将使用同一帐户对访问 Azure 的应用进行身份验证。
Azure CLI 如果开发人员已在 Azure CLI 中使用 az login 命令向 Azure 进行身份验证,则 DefaultAzureCredential 将使用同一帐户对访问 Azure 的应用进行身份验证。
Azure PowerShell 如果开发人员已在 Azure PowerShell 中使用 Connect-AzAccount cmdlet 向 Azure 进行身份验证,则 DefaultAzureCredential 将使用同一帐户对访问 Azure 的应用进行身份验证。
交互 如果已启用,DefaultAzureCredential 将通过当前系统的默认浏览器以交互方式对开发人员进行身份验证。 默认情况下禁用此选项。