You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 6 Blazor WASM应用间歇性出现IdentityServer密钥丢失问题

.NET Core 6 DataProtection + Azure 环境密钥环丢失问题排查与解决

核心问题

你的场景中,CryptographicException: 密钥{keyid}未在密钥环中找到 本质是ASP.NET Core DataProtection组件无法找到对应解密密钥,导致Duende IdentityServer无法解密存储的密钥材料。结合Azure App Service+Blob存储密钥+Key Vault加密的架构,问题根源集中在密钥环缓存刷新、存储同步、密钥生命周期管理三个维度。

具体原因及修复方案

1. 密钥环缓存未及时刷新

默认情况下,DataProtection会缓存密钥环24小时,仅在启动或缓存过期时才从Blob重新加载。若Blob中密钥更新(自动轮换),但App Service实例缓存未刷新,就会出现密钥找不到的情况。

修复步骤:

  • 显式配置密钥环刷新周期与密钥有效期,强制实例定期获取最新密钥:
    var keyVaultSettings = builder.Configuration.GetSection("KeyVault").Get<KeyVaultSettings>();
    
    builder.Services.AddDataProtection()
        .PersistKeysToAzureBlobStorage(keyVaultSettings.ConnectionString, keyVaultSettings.ContainerName, keyVaultSettings.BlobName)
        .ProtectKeysWithAzureKeyVault(new Uri(keyVaultSettings.KeyIdentifier), new DefaultAzureCredential())
        .SetDefaultKeyLifetime(TimeSpan.FromDays(7)) // 设置密钥有效期,按需调整
        .SetKeyRingRefreshPeriod(TimeSpan.FromHours(1)); // 每1小时刷新一次密钥环
    
  • 开启App Service的Always On功能,防止实例休眠导致缓存刷新机制失效。

2. Azure Blob存储一致性延迟

多实例部署时,某实例生成新密钥写入Blob后,其他实例可能因Blob默认的最终一致性无法立即读取新密钥,造成密钥环不一致。

修复步骤:

  • 将存储密钥的Blob或容器设置为强一致性(通过Azure Portal或CLI修改),确保所有实例能实时获取最新密钥文件。
  • 启用Blob变化监听,自动触发密钥环刷新:
    var blobClient = new BlobClient(keyVaultSettings.ConnectionString, keyVaultSettings.ContainerName, keyVaultSettings.BlobName);
    
    builder.Services.AddDataProtection()
        .PersistKeysToAzureBlobStorage(blobClient)
        .ProtectKeysWithAzureKeyVault(new Uri(keyVaultSettings.KeyIdentifier), new DefaultAzureCredential())
        .UseBlobStorageKeyWatcher(blobClient); // 监听Blob变化,自动刷新密钥环
    

    需确保引用Microsoft.AspNetCore.DataProtection.AzureStorage包,版本与.NET Core 6兼容。

3. Key Vault密钥轮换不匹配

若Key Vault密钥启用自动轮换,而DataProtection仍使用旧版本密钥解密,会导致密钥找不到错误。

修复步骤:

  • 确保DefaultAzureCredential拥有Key Vault的KeyGet权限,允许访问所有密钥版本。
  • 禁止手动删除Key Vault旧密钥版本,直到所有实例完成密钥环刷新(旧密钥需用于解密历史加密数据)。

4. 客户端缓存残留

常规窗口错误持续、无痕窗口正常的现象,说明客户端缓存了用失效密钥加密的身份验证Cookie/令牌。

修复步骤:

  • 缩短IdentityServer令牌过期时间,减少旧令牌有效时长:
    builder.Services.AddIdentityServer()
        // 生产环境替换为Key Vault签名密钥
        .AddSigningCredential(new Uri(keyVaultSettings.KeyIdentifier), new DefaultAzureCredential())
        .SetAccessTokenLifetime(TimeSpan.FromMinutes(15))
        .SetIdentityTokenLifetime(TimeSpan.FromMinutes(15));
    
  • 在应用重启后,通过响应头禁用客户端缓存:
    app.Use(async (context, next) =>
    {
        context.Response.Headers.CacheControl = "no-cache, no-store, must-revalidate";
        context.Response.Headers.Expires = "-1";
        await next();
    });
    

临时恢复优化

替代手动重启+无痕窗口的方式:

  • 使用Azure App Service部署槽位热重启:部署到staging槽后交换至生产槽,实例会逐步刷新,无服务中断。
  • 添加管理员接口触发密钥环刷新:
    [ApiController]
    [Route("api/dataprotection")]
    [Authorize(Roles = "Admin")]
    public class DataProtectionController : ControllerBase
    {
        private readonly IKeyManager _keyManager;
    
        public DataProtectionController(IKeyManager keyManager)
        {
            _keyManager = keyManager;
        }
    
        [HttpPost("refresh")]
        public IActionResult RefreshKeyRing()
        {
            _keyManager.RefreshKeyRing();
            return Ok("密钥环已刷新");
        }
    }
    

内容的提问来源于stack exchange,提问作者Chris Searles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:37:31