适用于 .NET 的 Azure 标识库的身份验证最佳做法
本文提供指南,帮助你在向 Azure 服务进行身份验证时最大程度地提高 .NET 应用的性能和可靠性。 若要充分利用适用于 .NET 的 Azure 标识库,请务必了解潜在问题和缓解技术。
在生产环境中使用确定性凭据
DefaultAzureCredential
是开始使用 Azure 标识库的最方便方法,但这种便利性也引入了某些权衡。 最明显的是,链中成功并用于请求身份验证的特定凭据无法提前保证。 在生产环境中,这种不可预测性可能会带来重大有时微妙的问题。
例如,请考虑以下假设的事件序列:
- 组织的安全团队要求所有应用都使用托管标识向 Azure 资源进行身份验证。
- 几个月来,托管在 Azure 虚拟机(VM)上的 .NET 应用成功使用
DefaultAzureCredential
通过托管标识进行身份验证。 - 开发人员无需告知支持团队,即可在该 VM 上安装 Azure CLI,并运行
az login
命令向 Azure 进行身份验证。 - 由于 Azure 环境中的单独配置更改,通过原始托管标识进行身份验证会意外开始以无提示方式失败。
DefaultAzureCredential
跳过失败的ManagedIdentityCredential
并搜索下一个可用凭据,该凭据AzureCliCredential
。- 应用程序开始使用 Azure CLI 凭据,而不是托管标识,这可能会失败或导致意外提升或减少特权。
若要防止生产应用中出现此类细微问题或无提示故障,强烈建议从 DefaultAzureCredential
迁移到以下确定性解决方案之一:
- 特定的
TokenCredential
实现,例如ManagedIdentityCredential
。 请参阅 派生列表 以获取选项。 - 针对运行应用的 Azure 环境优化的精简版
ChainedTokenCredential
实现。ChainedTokenCredential
本质上创建了一个可接受的凭据选项的特定允许列表,例如用于生产的ManagedIdentity
和用于开发的VisualStudioCredential
。
例如,请考虑在 ASP.NET Core 项目中的以下 DefaultAzureCredential
配置:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
DefaultAzureCredential credential = new();
clientBuilder.UseCredential(credential);
});
将上述代码替换为仅指定必要凭据的 ChainedTokenCredential
实现:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
clientBuilder.UseCredential(new ChainedTokenCredential(
new ManagedIdentityCredential(clientId: userAssignedClientId),
new VisualStudioCredential()));
});
在此示例中,ManagedIdentityCredential
将在生产环境中自动发现,而 VisualStudioCredential
可在本地开发环境中工作。
重用凭据实例
尽可能重复使用凭据实例以提高应用复原能力,并减少颁发给 Microsoft Entra ID 的访问令牌请求数。 重复使用凭据时,会尝试从基础 MSAL 依赖项管理的应用令牌缓存中提取令牌。 有关详细信息,请参阅 Azure 标识客户端库中 令牌缓存。
重要
不重复使用凭据的高容量应用可能会遇到来自 Microsoft Entra ID 的 HTTP 429 限制响应,这可能会导致应用中断。
建议的凭据重用策略因 .NET 应用程序类型而异。
采用 Microsoft.Extensions.Azure
的 UseCredential 方法实现凭据重用。 例如,假设 Azure 应用服务上托管 ASP.NET Core 应用,并设置了 UserAssignedClientId
环境变量。 .NET 配置提供程序确定存在环境变量,ManagedIdentityCredential
将用于对 Key Vault 机密和 Blob 存储客户端进行身份验证。 否则,将使用一系列链式的开发阶段凭据。
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddSecretClient(new Uri("<key-vault-url>"));
clientBuilder.AddBlobServiceClient(new Uri("<blob-storage-url>"));
string? clientId = builder.Configuration["UserAssignedClientId"];
TokenCredential credential = clientId is not null
? new ManagedIdentityCredential(
ManagedIdentityId.FromUserAssignedClientId(clientId))
: new ChainedTokenCredential(
new VisualStudioCredential(),
new AzureCliCredential(),
new AzurePowerShellCredential());
clientBuilder.UseCredential(credential);
});
有关此方法的信息,请参阅使用 Microsoft Entra ID 进行身份验证。
了解何时需要令牌生存期和缓存逻辑
如果你在依赖于 Azure Core 的 Azure SDK 客户端库环境之外使用 Azure 标识库凭据,则你有责任在应用中管理令牌生存期和缓存行为。
AccessToken
上的 RefreshOn 属性为消费者提供了一个提示,告诉他们何时可以尝试令牌刷新,它将被依赖于 Azure Core 库的 Azure SDK 客户端库自动使用来刷新令牌。 若要直接使用支持令牌缓存的 Azure 标识库凭据,当 RefreshOn
时间发生时,基础 MSAL 缓存会自动主动刷新。 此设计允许客户端代码每次需要令牌时调用 GetToken
,并将刷新操作委托给库。
若要仅在必要时调用 GetToken
,请观察 RefreshOn
日期,并主动尝试在该时间之后刷新令牌。 具体实现由客户决定。
了解托管标识重试策略
通过适用于 .NET 的 Azure 标识库,可以通过托管身份使用 ManagedIdentityCredential
进行身份验证。 使用 ManagedIdentityCredential
的方式会影响应用的重试策略。 通过以下方式使用时:
-
DefaultAzureCredential
,当初始令牌获取尝试失败或在短时间后超时时,不会尝试重试。 这是复原能力最低的选项,因为它被优化为“快速失败”,以实现高效的开发内部循环。 - 任何其他方法,例如直接使用
ChainedTokenCredential
或ManagedIdentityCredential
:默认情况下,重试之间的时间间隔从 0.8 秒开始,最多尝试 5 次重试。 此选项针对复原能力进行了优化,但在开发内部循环中引入了可能不需要的延迟。
若要更改任何默认重试设置,请使用
ManagedIdentityCredentialOptions
上的Retry
属性。 例如,最多重试三次,起始间隔为 0.5 秒:ManagedIdentityCredentialOptions miCredentialOptions = new( ManagedIdentityId.FromUserAssignedClientId(clientId) ) { Retry = { MaxRetries = 3, Delay = TimeSpan.FromSeconds(0.5), } }; ChainedTokenCredential tokenChain = new( new ManagedIdentityCredential(miCredentialOptions), new VisualStudioCredential() );
有关自定义重试策略的详细信息,请参阅 设置自定义重试策略。