将客户端机密用于Microsoft。Identity.Web

客户端密码是应用程序在从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用户机密

在本地开发期间存储机密的建议方法是 机密管理器工具。 用户机密将敏感数据存储在项目树之外,从而防止意外提交到源代码管理。

  1. 为您的项目初始化用户机密:

    dotnet user-secrets init
    
  2. 设置客户端机密值:

    dotnet user-secrets set "AzureAd:ClientCredentials:0:ClientSecret" "your-secret-value"
    
  3. 验证机密是否已存储:

    dotnet user-secrets list
    

在使用DevelopmentWebApplication.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 密钥保管库添加为配置源

  1. 安装所需的 NuGet 包:

    dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
    
  2. 将客户端密码存储在Azure 密钥保管库中,其名称映射到配置路径。 使用 -- (双短划线)作为分隔符:

    az keyvault secret set \
      --vault-name "your-keyvault-name" \
      --name "AzureAd--ClientCredentials--0--ClientSecret" \
      --value "your-secret-value"
    
  3. 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中为应用程序注册客户端密码:

  1. 登录到 Microsoft Entra 管理中心
  2. 导航到 Identity>Applications>应用注册
  3. 从列表中选择你的应用程序。
  4. 在左侧菜单中,选择 “证书和机密”。
  5. 选择 “客户端机密 ”选项卡。
  6. 选择 新客户端密码
  7. “添加客户端机密 ”窗格中:
    • 为该机密输入说明(例如,“开发机密”)。
    • 选择 有效期。 可用选项包括 180 天、365 天、730 天或自定义日期。
    • 选择 并添加
  8. 立即复制机密值。 该值仅显示一次,在离开页面后无法检索。

重要

创建后立即在安全位置记录机密值。 Microsoft Entra ID仅在创建时显示值。 如果丢失该值,则必须创建新的机密。

管理机密过期和轮换

客户端机密具有最长的生存期,并在创建期间指定的日期过期。 规划机密轮换以避免应用程序中断。

监视过期时间

  • 检查应用注册的“证书和机密”页中的“过期”列。
  • 设置 Microsoft Entra 建议以在凭据过期之前接收警报。

轮换策略

使用 ClientCredentials 数组支持零停机轮换:

  1. 在 Azure 门户中创建新的客户端密码。

  2. 将新机密添加为数组中的其他 ClientCredentials 条目。 先放置新秘钥,以便优先于旧秘钥进行尝试。

    {
      "AzureAd": {
        "ClientCredentials": [
          {
            "SourceType": "ClientSecret",
            "ClientSecret": "[NEW_SECRET_REFERENCE]"
          },
          {
            "SourceType": "ClientSecret",
            "ClientSecret": "[OLD_SECRET_REFERENCE]"
          }
        ]
      }
    }
    
  3. 部署更新的配置。 Microsoft.Identity.Web 尝试第一个凭据,如果第一个凭据验证失败,则回退到第二个凭据。

  4. 确认新机密正常工作后,请从配置和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中的应用注册所使用的密钥是为其他应用注册创建的。
  • 配置路径不正确,应用程序不会读取机密值。

解决方法:

  1. 在 Azure 门户中创建新的客户端密码,并仔细复制完整值。

  2. 验证您的配置中ClientIdTenantId的值,以确保它们与创建机密的应用注册相匹配。

  3. 添加断点或日志语句以验证配置是否已正确加载:

    // 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.

解决方法:

  1. 导航到Microsoft Entra 管理中心中的应用注册。
  2. 检查 证书和机密>客户端机密下的过期日期。
  3. 创建新的机密并更新应用程序配置。
  4. 从门户删除过期的机密。

配置中找不到机密

症状:应用程序会引发 或未能进行身份验证,因为机密值为 NullReferenceException

可能的原因:

  • 不会为项目初始化用户机密。
  • 环境变量名称与预期的配置路径不匹配。
  • 密钥保管库未被配置为配置源。
  • 应用程序在未加载用户机密的非开发环境中运行。

解决方法:

  1. 通过检查UserSecretsId文件中的.csproj来验证用户机密是否已初始化。
  2. 通过运行 dotnet user-secrets list验证机密是否已设置。
  3. 检查配置路径是否完全匹配: AzureAd:ClientCredentials:0:ClientSecret
  4. 如果在开发环境外部运行,请确保提供适当的配置源(环境变量或密钥保管库)。