客户端密码是应用程序在从Microsoft 标识平台请求令牌时用来证明其标识的字符串值。 Microsoft。Identity.Web 支持客户端机密作为机密客户端应用程序的多种凭据类型之一。
选择凭据类型
机密客户端应用程序需要凭据才能使用Microsoft 标识平台进行身份验证。 Microsoft。Identity.Web 通过 ClientCredentials 配置部分支持以下凭据类型:
| 凭据类型 | 建议的环境 | 安全级别 |
|---|---|---|
| 客户端密码 | 开发、测试 | 低 |
| 证书 | 过渡、生产 | 高 |
| 托管标识 | Azure托管的生产环境 | 最高 |
| 联合标识 | CI/CD、Kubernetes | 高 |
客户端机密是在 Microsoft Entra ID 中向应用注册的简单字符串。 虽然它们是设置的最简单凭据类型,但它们也存在重大安全限制:
- 可以在源代码、日志或配置文件中意外公开它们。
- 它们具有到期日期,必须手动轮换。
- 它们没有提供除了拥有机密之外的调用方身份的加密证明。
在 appsettings.json 中配置客户端密码
若要配置客户端密码,请将数组添加到ClientCredentialsAzureAd文件部分appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "YOUR_TENANT_ID",
"ClientId": "YOUR_CLIENT_ID",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "YOUR_SECRET_VALUE"
}
]
}
}
该 ClientCredentials 数组支持多个条目。 Microsoft。Identity.Web 会按顺序尝试每个凭据,直到一个凭据成功,这对于机密轮换方案非常有用。
警告
切勿将实际机密值提交到源代码管理。
YOUR_SECRET_VALUE前面的示例中的占位符必须替换为对安全存储的引用,如以下部分所述。
存储用于开发的机密
本部分介绍如何在本地开发期间将机密值从源代码中剔除。
.NET用户机密
在本地开发期间存储机密的建议方法是 机密管理器工具。 用户机密将敏感数据存储在项目树之外,从而防止意外提交到源代码管理。
为您的项目初始化用户机密:
dotnet user-secrets init设置客户端机密值:
dotnet user-secrets set "AzureAd:ClientCredentials:0:ClientSecret" "your-secret-value"验证机密是否已存储:
dotnet user-secrets list
在使用Development或WebApplication.CreateBuilder()时,用户机密会自动加载到Host.CreateDefaultBuilder()环境中。
您的 appsettings.json 应包含没有实际机密值的结构。
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "YOUR_TENANT_ID",
"ClientId": "YOUR_CLIENT_ID",
"ClientCredentials": [
{
"SourceType": "ClientSecret"
}
]
}
}
环境变量
还可以使用环境变量来提供客户端密码。 .NET配置会自动将使用 __ (双下划线) 分隔符的环境变量映射到配置层次结构。 为您的 shell 设置变量:
$env:AzureAd__ClientCredentials__0__ClientSecret = "your-secret-value"
环境变量中的值优先于 appsettings.json 中的值,因此配置文件中可以省略或留空秘密值。
为更高环境存储机密
对于过渡、QA 或任何共享环境,请使用Azure 密钥保管库作为配置源。 此方法使机密远离配置文件和环境变量,同时提供审核、访问策略和自动轮换功能。
将Azure 密钥保管库添加为配置源
安装所需的 NuGet 包:
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets将客户端密码存储在Azure 密钥保管库中,其名称映射到配置路径。 使用
--(双短划线)作为分隔符:az keyvault secret set \ --vault-name "your-keyvault-name" \ --name "AzureAd--ClientCredentials--0--ClientSecret" \ --value "your-secret-value"在
Program.cs中添加密钥保管库作为配置源。 以下代码注册密钥保管库,以便其机密可通过标准配置 API 获得:var builder = WebApplication.CreateBuilder(args); builder.Configuration.AddAzureKeyVault( new Uri("https://your-keyvault-name.vault.azure.net/"), new DefaultAzureCredential());
密钥保管库机密名称 AzureAd--ClientCredentials--0--ClientSecret会自动映射到 AzureAd:ClientCredentials:0:ClientSecret 配置路径。
小窍门
即使使用密钥保管库来存储客户端密码,请考虑生产工作负荷是否更好地由证书或托管标识提供服务。 密钥保管库适用于共享开发或过渡环境,但生产应用程序应使用更强的凭据类型。
在 Azure 门户中创建客户端密码
按照以下步骤在 Microsoft Entra ID中为应用程序注册客户端密码:
- 登录到 Microsoft Entra 管理中心。
- 导航到 Identity>Applications>应用注册。
- 从列表中选择你的应用程序。
- 在左侧菜单中,选择 “证书和机密”。
- 选择 “客户端机密 ”选项卡。
- 选择 新客户端密码。
- 在 “添加客户端机密 ”窗格中:
- 为该机密输入说明(例如,“开发机密”)。
- 选择 有效期。 可用选项包括 180 天、365 天、730 天或自定义日期。
- 选择 并添加。
- 立即复制机密值。 该值仅显示一次,在离开页面后无法检索。
重要
创建后立即在安全位置记录机密值。 Microsoft Entra ID仅在创建时显示值。 如果丢失该值,则必须创建新的机密。
管理机密过期和轮换
客户端机密具有最长的生存期,并在创建期间指定的日期过期。 规划机密轮换以避免应用程序中断。
监视过期时间
- 检查应用注册的“证书和机密”页中的“过期”列。
- 设置 Microsoft Entra 建议以在凭据过期之前接收警报。
轮换策略
使用 ClientCredentials 数组支持零停机轮换:
在 Azure 门户中创建新的客户端密码。
将新机密添加为数组中的其他
ClientCredentials条目。 先放置新秘钥,以便优先于旧秘钥进行尝试。{ "AzureAd": { "ClientCredentials": [ { "SourceType": "ClientSecret", "ClientSecret": "[NEW_SECRET_REFERENCE]" }, { "SourceType": "ClientSecret", "ClientSecret": "[OLD_SECRET_REFERENCE]" } ] } }部署更新的配置。 Microsoft.Identity.Web 尝试第一个凭据,如果第一个凭据验证失败,则回退到第二个凭据。
确认新机密正常工作后,请从配置和Azure门户中删除旧机密。
迁移到生产凭据
在部署到生产环境之前,请从客户端机密迁移到更安全的凭据类型:
基于证书的身份验证
证书提供身份的加密证明,并且是生产环境中建议使用的凭据类型。 以下配置从密钥保管库检索证书:
{
"AzureAd": {
"ClientCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://your-keyvault-name.vault.azure.net",
"KeyVaultCertificateName": "your-certificate-name"
}
]
}
}
有关详细步骤,请参阅 使用证书与 Microsoft.Identity.Web。
托管身份(无证书)
对于托管在 Azure 中的应用程序,托管标识服务无需管理凭据。 以下配置使用用户分配的托管标识:
{
"AzureAd": {
"ClientCredentials": [
{
"SourceType": "SignedAssertionFromManagedIdentity",
"ManagedIdentityClientId": "YOUR_MANAGED_IDENTITY_CLIENT_ID"
}
]
}
}
有关详细步骤,请参阅 Microsoft.Identity.Web 的无证书认证。
迁移核对清单
- [ ] 生成或预配新凭据(证书或托管标识)。
- [ ] 更新应用程序配置以使用新的凭据类型。
- [ ] 在过渡环境中测试新凭据。
- [ ] 部署到生产环境。
- [ ] 从 Azure 门户中删除旧的客户端密码。
- [ ] 在没有旧机密的情况下验证应用程序是否正常运行。
避免常见的安全错误
使用客户端机密时,请查看以下反模式及其建议的替代方法:
| 反模式 | 风险 | 建议 |
|---|---|---|
| 源代码中的硬编码机密 | 版本控制中公开的机密 | 使用用户机密、环境变量或密钥保管库 |
appsettings.Development.json使用机密提交 |
向具有存储库访问权限的任何人公开的机密 | 将文件添加到 .gitignore 并使用用户机密 |
| 跨环境共享机密 | 被破坏的开发秘密泄露至生产环境 | 每个环境使用唯一秘钥 |
| 在生产环境中使用机密 | 凭据被盗的风险更高 | 迁移到证书或托管身份 |
| 创建没有过期计划的机密 | 机密过期时应用程序中断 | 设置过期提醒并实现轮换 |
| 记录机密值 | 日志文件中公开的机密 | 从不记录凭据值;仅记录凭据源类型 |
| 将机密存储在服务器上的纯文本文件中 | 向具有服务器访问权限的任何人公开的机密 | 使用环境变量或密钥库 |
解决常见问题
本部分介绍配置客户端机密时可能会遇到的常见错误。
无效客户端机密
错误:AADSTS7000215: Invalid client secret provided.
可能的原因:
- 机密值被错误地复制。 机密值可以包含在复制/粘贴操作期间截断的特殊字符。
- 配置在
ClientId中的应用注册所使用的密钥是为其他应用注册创建的。 - 配置路径不正确,应用程序不会读取机密值。
解决方法:
在 Azure 门户中创建新的客户端密码,并仔细复制完整值。
验证您的配置中
ClientId和TenantId的值,以确保它们与创建机密的应用注册相匹配。添加断点或日志语句以验证配置是否已正确加载:
// For debugging only — remove before committing var config = builder.Configuration.GetSection("AzureAd:ClientCredentials:0:ClientSecret").Value; Console.WriteLine($"Secret loaded: {!string.IsNullOrEmpty(config)}");
客户端密码过期
错误:AADSTS7000222: The provided client secret keys for app '{app-id}' are expired.
解决方法:
- 导航到Microsoft Entra 管理中心中的应用注册。
- 检查 证书和机密>客户端机密下的过期日期。
- 创建新的机密并更新应用程序配置。
- 从门户删除过期的机密。
配置中找不到机密
症状:应用程序会引发 或未能进行身份验证,因为机密值为 NullReferenceException。
可能的原因:
- 不会为项目初始化用户机密。
- 环境变量名称与预期的配置路径不匹配。
- 密钥保管库未被配置为配置源。
- 应用程序在未加载用户机密的非开发环境中运行。
解决方法:
- 通过检查
UserSecretsId文件中的.csproj来验证用户机密是否已初始化。 - 通过运行
dotnet user-secrets list验证机密是否已设置。 - 检查配置路径是否完全匹配:
AzureAd:ClientCredentials:0:ClientSecret。 - 如果在开发环境外部运行,请确保提供适当的配置源(环境变量或密钥保管库)。
相关内容
- 在 Microsoft.Identity.Web 中使用证书
- 无证书身份验证
- 令牌缓存概述
在 ASP.NET Core 中开发时安全存储应用机密 - ASP.NET Core 中的 Azure 密钥保管库 配置提供程序