使用服务主体在本地开发期间向 Azure 服务验证 .NET 应用
在本地开发期间,应用程序需要向 Azure 进行身份验证才能访问各种 Azure 服务。 本地身份验证的两种常见方法是 使用开发人员帐户 或服务主体。 本文介绍如何使用应用程序服务主体。 在前面的部分中,你将了解:
- 如何使用 Microsoft Entra 注册应用程序以创建服务主体
- 如何使用 Microsoft Entra 组高效管理权限
- 如何将角色分配到范围权限
- 如何使用应用代码中的服务主体进行身份验证
使用专用应用程序服务主体,可以在访问 Azure 资源时遵守最低特权原则。 权限仅限于开发期间应用的特定要求,从而防止意外访问适用于其他应用或服务的 Azure 资源。 此方法还有助于避免在应用移至生产环境时出现的问题,确保其在开发环境中不拥有过多权限。
在 Azure 中注册应用时,会创建应用程序服务主体。 对于本地开发:
- 为每个正在处理应用的开发人员创建单独的应用注册,以确保每个开发人员都有自己的应用程序服务主体,避免需要共享凭据。
- 为每个应用创建单独的应用注册,以仅将应用的权限限制为必需内容。
在本地开发期间,使用应用程序服务主体的标识设置环境变量。 Azure 标识库读取这些环境变量,以向所需的 Azure 资源对应用进行身份验证。
在 Azure 中注册应用
使用 Azure 门户或 Azure CLI 通过 Azure 中的应用注册创建应用程序服务主体对象。
在 Azure 门户中,使用搜索栏导航到 应用注册 页。
在“应用注册”页上,选择“+ 新建注册”。
在“注册应用程序”页面上:
- 对于 名称 字段,请输入包含应用名称和目标环境的描述性值。
- 对于支持的帐户类型,请仅选择此组织目录中的帐户(仅限 Microsoft 客户引导 - 单租户),或选择最能满足你的要求的选项。
选择 注册 以注册应用并创建服务主体。
在应用的 应用注册 页上,复制 应用程序(客户端)ID 和 目录(租户)ID 并将其粘贴到临时位置,以便在应用代码配置中稍后使用。
选择“添加证书或机密”以设置应用的凭据。
在 证书 & 机密 页上,选择 + 新建客户端密码。
在打开的“添加客户端机密”打开的弹出面板中:
- 对于“说明”,请输入“当前”作为值。
- 对于“过期”值,请保留默认建议值 180 天。
- 选择“”,然后选择“”以添加密钥。
在 证书 & 密钥 页上,复制客户端密钥的 Value 属性,以便在将来的步骤中使用。
注意
创建应用注册后,客户端机密值仅显示一次。 无需使此客户端密码失效即可添加更多客户端机密,但无法再次显示此值。
创建用于本地开发的Microsoft Entra 组
创建Microsoft Entra 组来封装应用在本地开发中所需的角色(权限),而不是将角色分配给单个服务主体对象。 此方法具有以下优势:
- 每个开发人员在组级别都分配了相同的角色。
- 如果应用需要新角色,只需将角色添加到应用的组中。
- 如果新开发人员加入团队,则会为开发人员创建一个新的应用程序服务主体并将其添加到组中,确保开发人员有权处理应用。
在 Azure 门户中导航到 Microsoft Entra ID 概述页。
从左侧菜单中选择“所有组”。
在 组 页面上,选择 新组。
在“新建组”页上,填写以下表单字段:
- “组类型”:选择“安全性”。
- 组名称:输入包含对应用或环境名称的引用的组的名称。
- 组说明:输入用于解释该组目的的说明。
在“成员”下选择“未选择成员”链接,以将成员添加到组中。
在打开的浮出控件面板中,搜索之前创建的服务主体,并从筛选的结果中选择它。 在面板底部选择“选择”按钮以确认您的选择。
选择“新建组”页底部的“创建”,以创建组并返回到“所有组”页。 如果未看到列出的新组,请稍等片刻并刷新页面。
将角色分配到组
接下来,确定应用在哪些资源上需要哪些角色(权限),并将这些角色分配给创建的 Microsoft Entra 组。 可以在资源、资源组或订阅范围内为组分配角色。 此示例演示如何在资源组范围内分配角色,因为大多数应用将其所有 Azure 资源分组到单个资源组中。
在 Azure 门户中,导航到包含应用的资源组的 概述 页。
在左侧导航栏中,选择访问控制 (IAM)。
在 访问控制(IAM) 页上,选择 + 添加,然后从下拉菜单中选择 添加角色分配。 “添加角色分配” 页提供了多个选项卡来配置和分配角色。
在“角色”选项卡上,使用搜索框找到要分配的角色。 选择该角色,然后选择 下一步。
在“成员”选项卡上:
- 对于“将访问权限分配到”值,请选择“用户、组或服务主体”。
- 对于“成员”值,请选择“+ 选择成员”,以打开“选择成员”弹出面板。
- 搜索之前创建的Microsoft Entra 组,并从筛选的结果中选择它。 选择“选择”来选择组并关闭弹出面板。
- 在“成员”选项卡的底部,选择“查看 + 分配”。
在 审阅 + 分配 选项卡上,选择页面底部的审阅 + 分配。
设置应用环境变量
在运行时,来自 Azure 标识库的某些凭据(例如 DefaultAzureCredential
、EnvironmentCredential
和 ClientSecretCredential
)按约定在环境变量中搜索服务主体信息。 使用 .NET 时,有多种方法可以配置环境变量,具体取决于工具和环境。
无论选择哪种方法,都为服务主体配置以下环境变量:
AZURE_CLIENT_ID
:用于标识 Azure 中注册的应用。-
AZURE_TENANT_ID
:Microsoft Entra 租户的 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": "<your-client-id>",
"AZURE_TENANT_ID":"<your-tenant-id>",
"AZURE_CLIENT_SECRET": "<your-client-secret>"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"AZURE_CLIENT_ID": "<your-client-id>",
"AZURE_TENANT_ID":"<your-tenant-id>",
"AZURE_CLIENT_SECRET": "<your-client-secret>"
}
}
}
从应用向 Azure 服务进行身份验证
Azure 标识库提供了各种凭据— TokenCredential
的实现适用于支持不同方案和 Microsoft Entra 身份验证流。 前面的步骤演示了在本地和生产环境中使用服务主体时,如何使用 ClientSecretCredential。
实现代码
添加 Azure.Identity 包。 在 ASP.NET Core 项目中,还安装 Microsoft.Extensions.Azure 包:
在所选终端中,导航到应用程序项目目录并运行以下命令:
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure
Azure 服务使用各种 Azure SDK 客户端库中的专用客户端类进行访问。 应注册这些类和你自己的自定义服务进行依赖项注入,以便在整个应用中使用它们。 在 Program.cs
中,完成以下步骤,为依赖项注入和基于令牌的身份验证配置客户端类:
- 通过
using
指令包括Azure.Identity
和Microsoft.Extensions.Azure
命名空间。 - 使用相应的
Add
前缀扩展方法注册 Azure 服务客户端。 - 使用
tenantId
、clientId
和clientSecret
配置ClientSecretCredential
。 - 将
ClientSecretCredential
实例传递给UseCredential
方法。
builder.Services.AddAzureClients(clientBuilder =>
{
var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
clientBuilder.UseCredential(new ClientSecretCredential(tenantId, clientId, clientSecret));
});
UseCredential
方法的替代方法是直接向服务客户端提供凭据:
var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
builder.Services.AddSingleton<BlobServiceClient>(_ =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"),
new ClientSecretCredential(tenantId, clientId, clientSecret)));