使用服务主体在本地开发期间向 Azure 服务验证 .NET 应用的身份
开发人员需要在其本地工作站上调试和测试云应用。 在本地开发期间,当应用在开发人员的工作站上运行时,它仍然必须向应用使用的任何 Azure 服务进行身份验证。 本文介绍如何设置要在本地开发期间使用的专用应用程序服务主体对象。
使用用于本地开发的专用应用程序服务主体可以在应用开发期间遵循最低特权原则。 由于权限的范围严格限定为开发期间应用所需的权限,因此可以防止应用代码意外访问仅供其他应用使用的 Azure 资源。 在将应用转移到生产环境时,这还可以防止出现 bug,因为该应用在开发环境中特权过高。
在 Azure 中注册应用时,将为该应用设置应用程序服务主体。 为本地开发注册应用时,建议执行以下操作:
- 为每个使用应用的开发人员创建单独的应用注册。 这会为每个开发人员单独创建要在本地开发期间使用的应用程序服务主体,并避免开发人员共享单个应用程序服务主体的凭据的需要。
- 为每个应用创建单独的应用注册。 这会将应用的权限范围限定为该应用所需的权限。
在本地开发期间,将使用应用程序服务主体的标识设置环境变量。 Azure 标识库读取这些环境变量,并使用此信息对访问所需 Azure 资源的应用进行身份验证。
1 - 在 Azure 中注册应用程序
应用程序服务主体对象是使用 Azure 中的应用注册创建的。 可以使用 Azure 门户或 Azure CLI 完成此操作。
登录到 Azure 门户并执行以下步骤。
2 - 为本地开发创建 Microsoft Entra 组
由于通常会有多个开发人员处理一个应用,因此建议创建一个 Microsoft Entra 组来封装应用在本地开发中所需的角色(权限),而不要将角色分配到单个服务主体对象。 此方法提供以下优势:
- 由于角色是在组级别分配的,因此可以确保为每个开发人员分配相同的角色。
- 如果应用需要新角色,只需将此角色添加到应用的组即可。
- 如果有新的开发人员加入团队,请为该开发人员创建一个新的应用程序服务主体并将其添加到该组中,以确保开发人员拥有正确的权限来处理应用。
3 - 将角色分配到应用程序
接下来,请确定应用在哪些资源上需要哪些角色(权限),并将这些角色分配到应用。 在此示例中,角色将分配给在步骤 2 中创建的 Microsoft Entra 组。 可以在资源、资源组或订阅范围分配组。 此示例演示如何在资源组范围分配角色,因为大多数应用将其所有 Azure 资源分组到单个资源组中。
4 - 设置应用程序环境变量
在运行时,DefaultAzureCredential
在环境变量集合中查找服务主体信息。 使用 .NET 时,可以根据你的工具和环境以多种方式配置环境变量。
无论选择哪种方法,都请在处理服务主体时配置以下环境变量:
AZURE_CLIENT_ID
→ 应用 ID 值。AZURE_TENANT_ID
→ 租户 ID 值。AZURE_CLIENT_SECRET
→ 为应用生成的密码/凭据。
在本地使用 Visual Studio 时,可以在项目的 Properties
文件夹中的 launchsettings.json
文件内设置环境变量。 当应用启动时,会自动拉入这些值。 请记住,这些配置在部署时不会随应用一起移动,因此需要在目标托管环境中设置环境变量。
"profiles": {
"SampleProject": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7177;http://localhost:5177",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"AZURE_CLIENT_ID": "00000000-0000-0000-0000-000000000000",
"AZURE_TENANT_ID":"11111111-1111-1111-1111-111111111111",
"AZURE_CLIENT_SECRET": "=abcdefghijklmnopqrstuvwxyz"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"AZURE_CLIENT_ID": "00000000-0000-0000-0000-000000000000",
"AZURE_TENANT_ID": "11111111-1111-1111-1111-111111111111",
"AZURE_CLIENT_SECRET": "=abcdefghijklmnopqrstuvwxyz"
}
}
}
5 - 在应用程序中实现 DefaultAzureCredential
DefaultAzureCredential 是一个固定的有序机制序列,用于向 Microsoft Entra 进行身份验证。 每个身份验证机制都是一个派生自 TokenCredential 类的类,称为“凭据”。 在运行时,DefaultAzureCredential
尝试使用第一个凭据进行身份验证。 如果该凭据无法获取访问令牌,则会尝试序列中的下一个凭据,以此类推,直到成功获取访问令牌。 这样,应用就可在不同的环境中使用不同的凭据,而无需编写特定于环境的代码。
DefaultAzureCredential
按哪种顺序和在哪个位置查找凭据见于 DefaultAzureCredential。
若要使用 DefaultAzureCredential
,请将 Azure.Identity 和 Microsoft.Extensions.Azure 包添加到应用程序:
在所选终端中,导航到应用程序项目目录并运行以下命令:
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure
使用各种 Azure SDK 客户端库中的专用客户端类访问 Azure 服务。 应注册这些类和你自己的自定义服务,以便可以在整个应用中通过依赖项注入来访问它们。 在 Program.cs
中,完成以下步骤以注册客户端类和 DefaultAzureCredential
:
- 通过
using
指令包含Azure.Identity
和Microsoft.Extensions.Azure
命名空间。 - 使用相应的
Add
前缀扩展方法注册 Azure 服务客户端。 - 将
DefaultAzureCredential
的实例传递给UseCredential
方法。
例如:
using Microsoft.Extensions.Azure;
using Azure.Identity;
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
clientBuilder.UseCredential(new DefaultAzureCredential());
});
UseCredential
的替代方法是直接实例化 DefaultAzureCredential
:
using Azure.Identity;
builder.Services.AddSingleton<BlobServiceClient>(_ =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"),
new DefaultAzureCredential()));
上述代码在本地开发工作站上运行时,它会在应用程序服务主体的环境变量或本地安装的开发人员工具(如 Visual Studio)中查找一组开发人员凭据。 在本地开发期间,两种方法都可用于对访问 Azure 资源的应用进行身份验证。
部署到 Azure 时,此代码也可以对访问 Azure 资源的应用进行身份验证。 DefaultAzureCredential
可以检索环境设置和托管标识配置,以自动向其他服务进行身份验证。