向其他 Azure 资源验证 Azure 托管应用的建议方法是使用 托管标识。 大多数 Azure 服务 都支持此方法,包括 Azure 应用服务、Azure 容器应用和 Azure 虚拟机上托管的应用。 在 身份验证概述 页上详细了解不同的身份验证技术和方法。 在前面的部分中,你将了解:
- 基本托管标识概念
- 如何为应用创建用户分配的托管标识
- 如何为用户分配的托管标识分配角色
- 如何通过应用代码使用用户分配的托管标识进行身份验证
基本托管标识概念
托管标识使应用能够安全地连接到其他 Azure 资源,而无需使用密钥或其他应用程序机密。 在内部,Azure 会跟踪身份以及其被允许连接的资源。 Azure 使用此信息自动获取应用的 Microsoft Entra 令牌,以允许它连接到其他 Azure 资源。
配置托管应用时,需要考虑两种类型的托管标识:
- 系统分配的托管身份是在 Azure 资源上直接启用的,并绑定于其生命周期。 当资源被删除时,Azure 会自动为你删除标识。 系统分配的标识提供了使用托管标识的极简方法。
- 用户分配的 托管标识作为独立的 Azure 资源创建,提供更高的灵活性和更多的功能。 它们非常适合涉及多个需要共享相同标识和权限的 Azure 资源的解决方案。 例如,如果多个虚拟机需要访问同一组 Azure 资源,则用户分配的托管标识可提供可重用性和优化管理。
小窍门
在托管标识 最佳做法建议 文章中,详细了解如何选择和管理系统分配的托管标识和用户分配的托管标识。
前面的部分介绍了为 Azure 托管应用启用和使用用户分配的托管标识的步骤。 如果需要使用系统分配的托管标识,请访问 系统分配的托管标识 文章了解详细信息。
创建用户分配的托管标识
用户分配的托管标识是使用 Azure 门户或 Azure CLI 在 Azure 订阅中作为独立资源创建的。 Azure CLI 命令可以在 Azure Cloud Shell 中或是安装了 Azure CLI 的工作站上运行。
在 Azure 门户中,在主搜索栏中输入 托管标识 ,并在 “服务 ”部分下选择匹配结果。
在托管标识页面上,选择+ 创建。
在“ 创建用户分配的托管标识 ”页上,为用户分配的托管标识选择订阅、资源组和区域,然后提供名称。
选择 “审阅 + 创建 ”以查看并验证输入。
选择“ 创建 ”以创建用户分配的托管标识。
创建标识后,选择“ 转到资源”。
在新标识的 “概述 ”页上,复制 客户端 ID 值,以便在以后配置应用程序代码时使用。
使用 Azure CLI 命令 az identity create
创建托管标识:
az identity create \
--resource-group <resource-group-name> \
--name <identity-name> \
--query 'clientId' \
--output json
该命令输出将输出所创建用户分配的托管标识的客户端 ID。 客户端 ID 用于配置依赖于标识的应用程序代码。
你可以随时使用命令 az identity show
再次查看托管标识属性。
az identity show \
--resource-group <your-resource-group> \
--name <your-managed-identity-name> \
--output json
将托管身份标识分配给您的应用程序
用户分配的托管标识可以与一个或多个 Azure 资源相关联。 使用该标识的所有资源都通过该标识的角色获得应用的权限。
在 Azure 门户中,导航到托管应用代码的资源,例如 Azure 应用服务或 Azure 容器应用实例。
在资源的 概述 页中,展开 设置,并从导航菜单中选择 身份。
在“标识”页上,切换到“用户分配”选项卡。
选择 “+ 添加” 以打开 “添加用户分配的托管标识 ”面板。
在 添加用户分派管理身份 面板中,使用 订阅 下拉列表筛选身份的搜索结果。 使用 “用户分配的托管标识 ”搜索框查找为托管应用的 Azure 资源启用的用户分配托管标识。
选择标识,然后选择面板底部的 “添加” 以继续。
Azure CLI 提供了不同的命令,用于将用户分配的托管标识分配给不同类型的托管服务。
若要使用 Azure CLI 将用户分配托管的标识分配给资源(例如 Azure 应用服务中的 Web 应用),您将需要该标识的资源 ID。 az identity show
使用命令检索资源 ID:
az identity show \
--resource-group <your-resource-group> \
--name <your-managed-identity-name> \
--output json \
--query id
获得资源 ID 后,使用 Azure CLI 命令 az <resourceType> identity assign
将用户分配的托管标识与不同的资源相关联,如下所示:
对于 Azure 应用服务,请使用 Azure CLI 命令 az webapp identity assign
:
az webapp identity assign \
--resource-group <resource-group-name> \
--name <webapp-name> \
--identities <user-assigned-identity-resource-id>
对于 Azure 容器应用,请使用 Azure CLI 命令 az containerapp identity assign
:
az containerapp identity assign \
--resource-group <resource-group-name> \
--name <containerapp-name> \
--identities <user-assigned-identity-resource-id>
对于 Azure 虚拟机,请使用 Azure CLI 命令 az vm identity assign
:
az vm identity assign \
--resource-group <resource-group-name> \
--name <vm-name> \
--identities <user-assigned-identity-resource-id>
为托管标识分配角色
接下来,确定应用需要哪些角色并将这些角色分配给托管标识。 你可以为托管标识分配以下范围内的角色:
- 资源:分配的角色仅适用于该特定资源。
- 资源组:分配的角色适用于资源组中包含的所有资源。
- 订阅:被分配的角色适用于订阅中包含的所有资源。
以下示例演示如何在资源组范围内分配角色,因为许多应用使用单个资源组管理其所有相关的 Azure 资源。
导航到包含具有用户分配托管标识的应用的资源组的 “概述 ”页。
在左侧导航栏中,选择“访问控制(IAM)”。
在 访问控制(IAM) 页上,选择顶部菜单上的 + 添加,然后选择 添加角色分配 导航到 添加角色分配 页。
“添加角色分配”页展示了一个分步骤的选项卡式工作流程,用于将角色分配给标识。 在初始“角色”选项卡上,使用顶部的搜索框来定位你想要分配给标识的角色。
从结果中选择角色,然后选择 “下一步” 以进入“成员”选项卡。
对于“将访问权限分配到”选项,请选择“托管标识”。
对于“成员”选项,请选择“+ 选择成员”,以打开“选择托管标识”面板。
在 选择托管标识 面板中,使用 订阅 和 托管标识 下拉列表来筛选标识的搜索结果。 使用选择搜索框查找为托管应用的 Azure 资源启用的用户分配的托管标识。
选择标识,并在面板底部选择选择以继续。
选择页面底部的“查看 + 分配”。
在最终的 审阅 + 分配 选项卡中,选择 审阅 + 分配 以完成整个工作流程。
若要使用 Azure CLI 将角色分配给用户分配的托管标识,你需要获取该标识的主体 ID。 使用az identity show
命令检索主体 ID。
az identity show \
--resource-group <your-resource-group> \
--name <your-managed-identity-name> \
--output json \
--query principalId
使用 az role definition list 命令来查看可分配给托管标识的角色:
az role definition list \
--query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
--output table
使用 az role assignment create 命令为托管标识分配角色:
az role assignment create \
--assignee <your-principal-id> \
--role <role-name> \
--scope <scope>
例如,若要允许 ID 为 99999999-9999-9999-9999-999999999999
的托管主体对 msdocs-dotnet-sdk-auth-example 资源组中的所有存储帐户的 Azure 存储 blob 容器和数据进行读取、写入和删除访问,你可以使用以下命令将应用程序服务主体分配给存储 Blob 数据参与者角色:
az role assignment create \
--assignee 99999999-9999-9999-9999-999999999999 \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/msdocs-dotnet-sdk-auth-example"
有关使用 Azure CLI 在资源或订阅级别分配权限的信息,请参阅使用 Azure CLI 分配 Azure 角色一文。
从应用向 Azure 服务进行身份验证
Azure 标识库提供了各种凭据— TokenCredential
的实现适用于支持不同方案和 Microsoft Entra 身份验证流。 由于托管标识在本地运行时不可用,因此后续步骤演示了在哪种方案中要使用的凭据:
实现代码
添加 Azure.Identity 包。 在 ASP.NET Core 项目中,还安装 Microsoft.Extensions.Azure 包:
在所选终端中,导航到应用程序项目目录并运行以下命令:
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure
在 Visual Studio 解决方案资源管理器 窗口中右键单击项目,然后选择 管理 NuGet 包。 搜索 Azure.Identity,并安装匹配的包。 对 Microsoft.Extensions.Azure 包重复此过程。
Azure 服务使用各种 Azure SDK 客户端库中的专用客户端类进行访问。 应注册这些类和你自己的自定义服务进行依赖项注入,以便在整个应用中使用它们。 在 Program.cs
中,完成以下步骤,为依赖项注入和基于令牌的身份验证配置客户端类:
- 通过
Azure.Identity
指令包括 Microsoft.Extensions.Azure
和 using
命名空间。
- 使用相应的
Add
前缀扩展方法注册 Azure 服务客户端。
- 将适当的
TokenCredential
实例传递给 UseCredential
方法:
- 在本地运行应用时使用
DefaultAzureCredential
- 在 Azure 中运行应用并配置客户端 ID、资源 ID 或对象 ID 时使用
ManagedIdentityCredential
。
客户端 ID 用于在配置需要使用该标识进行身份验证的应用程序或服务时标识托管标识。
使用以下命令检索分配给用户分配的托管身份的客户端 ID:
az identity show \
--resource-group <resource-group-name> \
--name <identity-name> \
--query 'clientId'
将 ManagedIdentityCredential
配置为客户端 ID:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
TokenCredential credential = null;
if (builder.Environment.IsProduction() || builder.Environment.IsStaging())
{
// Managed identity token credential discovered when running in Azure environments
credential = new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedClientId("<client-id>"));
}
else
{
// Running locally on dev machine - DO NOT use in production or outside of local dev
credential = new DefaultAzureCredential();
}
clientBuilder.UseCredential(credential);
});
UseCredential
方法的替代方法是直接向服务客户端提供凭据:
TokenCredential credential = null;
if (builder.Environment.IsProduction() || builder.Environment.IsStaging())
{
// Managed identity token credential discovered when running in Azure environments
credential = new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedClientId("<client-id>"));
}
else
{
// Running locally on dev machine - DO NOT use in production or outside of local dev
credential = new DefaultAzureCredential();
}
builder.Services.AddSingleton<BlobServiceClient>(_ =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"), credential));
资源 ID 使用以下结构唯一标识 Azure 订阅中的托管标识资源:
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}
资源 ID 可以按照约定生成,这样在环境中使用大量用户分配的托管标识时会更方便。
使用以下命令检索用户分配托管标识的资源 ID:
az identity show \
--resource-group <resource-group-name> \
--name <identity-name> \
--query 'id'
使用资源 ID 配置 ManagedIdentityCredential
:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
TokenCredential credential = null;
if (builder.Environment.IsProduction() || builder.Environment.IsStaging())
{
// Managed identity token credential discovered when running in Azure environments
credential = new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedResourceId(new ResourceIdentifier("<resource-id>")));
}
else
{
// Running locally on dev machine - DO NOT use in production or outside of local dev
credential = new DefaultAzureCredential();
}
clientBuilder.UseCredential(credential);
});
UseCredential
方法的替代方法是直接向服务客户端提供凭据:
TokenCredential credential = null;
if (builder.Environment.IsProduction() || builder.Environment.IsStaging())
{
// Managed identity token credential discovered when running in Azure environments
credential = new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedResourceId(new ResourceIdentifier("<resource-id>")));
}
else
{
// Running locally on dev machine - DO NOT use in production or outside of local dev
credential = new DefaultAzureCredential();
}
builder.Services.AddSingleton<BlobServiceClient>(_ =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"), credential));
主体 ID 是对象 ID 的另一个名称。
使用以下命令检索用户分配托管标识的对象 ID:
az identity show \
--resource-group <resource-group-name> \
--name <identity-name> \
--query 'principalId'
使用对象 ID 配置 ManagedIdentityCredential
:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
TokenCredential credential = null;
if (builder.Environment.IsProduction() || builder.Environment.IsStaging())
{
// Managed identity token credential discovered when running in Azure environments
credential = new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedObjectId("<object-id>"));
}
else
{
// Running locally on dev machine - DO NOT use in production or outside of local dev
credential = new DefaultAzureCredential();
}
clientBuilder.UseCredential(credential);
});
UseCredential
方法的替代方法是直接向服务客户端提供凭据:
TokenCredential credential = null;
if (builder.Environment.IsProduction() || builder.Environment.IsStaging())
{
// Managed identity token credential discovered when running in Azure environments
credential = new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedObjectId("<object-id>"));
}
else
{
// Running locally on dev machine - DO NOT use in production or outside of local dev
credential = new DefaultAzureCredential();
}
builder.Services.AddSingleton<BlobServiceClient>(_ =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"), credential));
上述代码的行为因运行环境而异:
- 在本地开发工作站上,
DefaultAzureCredential
查找应用程序服务主体的环境变量,或在 Visual Studio 等本地安装的开发人员工具中查找一组开发人员凭据。
- 部署到 Azure 时,
ManagedIdentityCredential
会自动检测托管标识配置,以便对其他服务进行身份验证。