你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

配置多个 Azure 应用和服务之间的无密码连接

应用程序通常需要同时在多个 Azure 服务之间建立安全连接。 例如,一个企业 Azure 应用服务实例可能会连接到多个不同的存储帐户、一个 Azure SQL 数据库实例、一个服务总线等。

建议使用托管标识身份验证,以便在 Azure 资源之间建立安全的无密码连接。 开发人员不必手动跟踪和管理托管标识的许多不同机密,因为这些任务大多由 Azure 在内部处理。 本教程介绍如何使用托管标识和 Azure 标识客户端库管理多个服务之间的连接。

对比托管标识的类型

Azure 提供以下类型的托管标识:

  • 系统分配的标识:直接链接到单个 Azure 资源。 在服务上启用系统分配的托管标识时,Azure 将创建链接标识并在内部处理该标识的管理任务。 删除 Azure 资源时也会删除该标识。
  • 用户分配的托管标识:由管理员创建的独立标识,可与一个或多个 Azure 资源相关联。 标识的生命周期独立于这些资源。

可以阅读标识最佳做法建议详细了解相关最佳做法、何时使用系统分配的标识以及何时使用用户分配的标识。

探索 DefaultAzureCredential

通常情况下,托管标识通过 Azure.Identity 客户端库中名为 DefaultAzureCredential 的类,在应用程序代码中进行实现。 DefaultAzureCredential 支持多种身份验证方法,并自动确定应在运行时使用哪些方法。 可以在 DefaultAzureCredential 概述中详细了解此方法。

将 Azure 托管应用连接到多个 Azure 服务

你的任务是使用无密码连接将一个现有应用连接到多个 Azure 服务和数据库。 该应用程序是托管在 Azure 应用服务上的 ASP.NET Core Web API,但以下步骤也适用于其他 Azure 托管环境,例如 Azure Spring Apps、虚拟机、容器应用和 AKS。

本教程适用于以下体系结构,但通过少量配置更改也可适用于许多其他方案。

Diagram showing the user assigned identity relationships.

以下步骤演示了如何配置应用,使其使用系统分配的托管标识和本地开发帐户来连接到多个 Azure 服务。

创建系统分配的托管标识

  1. 在 Azure 门户中,导航到要连接到其他服务的托管应用程序。

  2. 在“服务概述”页面上,选择“标识”。

  3. 将“状态”设置切换为“打开”,从而为服务启用系统分配的托管标识。

    Screenshot showing how to assign a system assigned managed identity.

将角色分配给每个连接服务的托管标识

  1. 导航到存储帐户的概述页面,你将授予该帐户你的标识访问权限。

  2. 从存储帐户导航中选择“访问控制(IAM)”。

  3. 依次选择“+ 添加”和“添加角色分配”。

    Screenshot showing how to assign a system-assigned identity.

  4. 在“角色”搜索框中,搜索“存储 Blob 数据参与者”,该参与者可授予对 Blob 数据执行读取和写入操作的权限。 可以分配适合你的用例的任何角色。 从列表中选择“存储 Blob 数据参与者”,然后选择“下一步”。

  5. 在“添加角色分配”屏幕上,针对“将访问权限分配给”选项,请选择“托管标识”。 然后选择“+选择成员”。

  6. 在浮出控件中,通过输入应用服务的名称搜索创建的托管标识。 选择系统分配的标识,然后选择“选择”以关闭浮出控件菜单。

    Screenshot showing how to select a system-assigned identity.

  7. 多次选择“下一步”,直到可以选择“查看+分配”,以完成角色分配。

  8. 针对要连接到的其他服务,重复此过程。

本地开发注意事项

通过向用户帐户分配角色(方式与向托管标识分配角色一样),也可以实现对 Azure 资源的访问,以进行本地开发。

  1. 将“存储 Blob 数据参与者”角色分配给托管标识后,这次请在“将访问权限分配到”下,选择“用户、组或服务主体”。 选择“+ 选择成员”,再次打开浮出控件菜单。

  2. 搜索并选择你希望通过电子邮件地址或名称授予其访问权限的 user@domain 帐户或 Microsoft Entra 安全组。 这应该是你用来登录本地开发工具(如 Visual Studio 或 Azure CLI)的同一账户。

注意

如果是与多个开发人员合作,还可以将这些角色分配给 Microsoft Entra 安全组。 然后,可以将需要访问权限以在本地开发应用的任何开发人员放入该组中。

实现应用程序代码

在项目中,添加对 Azure.Identity NuGet 包的引用。 此库包含实现 DefaultAzureCredential 所需的全部实体。 也可以添加与应用相关的任何其他 Azure 库。 例如,添加 Azure.Storage.BlobsAzure.KeyVault.Keys 包,以便连接到 Blob 存储和密钥保管库。

dotnet add package Azure.Identity
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.KeyVault.Keys

Program.cs 文件的顶部,添加以下 using 语句:

using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Security.KeyVault.Keys;

在项目代码的 Program.cs 文件中,创建应用将连接到的必要服务的实例。 以下示例使用相应的 SDK 类连接到 Blob 存储和服务总线。

var blobServiceClient = new BlobServiceClient(
    new Uri("https://<your-storage-account>.blob.core.windows.net"),
    new DefaultAzureCredential(credOptions));

var serviceBusClient = new ServiceBusClient("<your-namespace>", new DefaultAzureCredential());
var sender = serviceBusClient.CreateSender("producttracking");

在本地运行此应用程序代码时,DefaultAzureCredential 将在凭证链中搜索首个可用凭证。 如果 Managed_Identity_Client_ID 在本地为 null,则其将自动使用本地 Azure CLI 或 Visual Studio 登录中的凭据。 可以在 Azure 标识库概述中详细了解此过程。

将应用程序部署到 Azure 后,DefaultAzureCredential 将自动从应用服务环境中检索 Managed_Identity_Client_ID 变量。 当托管标识与应用关联时,该值将变为可用。

整个这一过程可确保应用能够在本地和 Azure 中安全运行,而无需进行任何代码更改。

使用多个托管标识连接多个应用

尽管上一示例中,所有应用的服务访问要求都相同,但实际环境中通常存在着细微差异。 假设以下场景:多个应用都连接到同一存储帐户,但其中两个应用还访问不同的服务或数据库。

Diagram showing multiple user-assigned managed identities.

若要在代码中配置此设置,请确保应用程序注册单独的服务来连接到每个存储帐户或数据库。 在配置 DefaultAzureCredential 时,请确保为每个服务拉取正确的托管标识客户端 ID。 以下代码示例配置了下列服务连接:

  • 到单独存储帐户的两个连接(使用共享的用户分配托管标识)
  • 到 Azure Cosmos DB 和 Azure SQL 服务的连接(使用另一个共享的用户分配托管标识)
// Get the first user-assigned managed identity ID to connect to shared storage
const clientIdStorage = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID_Storage");

// First blob storage client that using a managed identity
BlobServiceClient blobServiceClient = new BlobServiceClient(
    new Uri("https://<receipt-storage-account>.blob.core.windows.net"),
    new DefaultAzureCredential()
    {
        ManagedIdentityClientId = clientIDstorage
    });

// Second blob storage client that using a managed identity
BlobServiceClient blobServiceClient2 = new BlobServiceClient(
    new Uri("https://<contract-storage-account>.blob.core.windows.net"),
    new DefaultAzureCredential()
    {
        ManagedIdentityClientId = clientIDstorage
    });


// Get the second user-assigned managed identity ID to connect to shared databases
var clientIDdatabases = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID_Databases");

// Create an Azure Cosmos DB client
CosmosClient client = new CosmosClient(
    accountEndpoint: Environment.GetEnvironmentVariable("COSMOS_ENDPOINT", EnvironmentVariableTarget.Process),
    new DefaultAzureCredential()
    {
        ManagedIdentityClientId = clientIDdatabases
    });

// Open a connection to Azure SQL using a managed identity
string ConnectionString1 = @"Server=<azure-sql-hostname>.database.windows.net; User Id=ObjectIdOfManagedIdentity; Authentication=Active Directory Default; Database=<database-name>";

using (SqlConnection conn = new SqlConnection(ConnectionString1))
{
    conn.Open();
}

还可以将用户分配的托管标识以及系统分配的托管标识同时关联到资源。 这样做在以下场景会很有帮助,即所有应用都需要访问同一共享服务,但其中一个应用还对其他服务具有特定的依赖关系。 使用系统分配的标识还可以确保在删除特定应用的同时,也删除与其相关联的标识,这有助于清理环境。

Diagram showing user-assigned and system-assigned managed identities.

标识最佳做法建议中更加深入地探讨了这些类型的方案。

后续步骤

本教程介绍了如何将应用程序迁移到无密码连接。 可以阅读以下资源,更深入地了解本文中讨论的概念: