.NET Core 6极简托管模型:如何在ConfigureServices中获取Azure KeyVault密钥
解决.NET Core 6 Worker应用中ConfigureServices访问Azure KeyVault密钥的问题
核心问题分析
你当前的代码存在两个关键问题:
- 配置构建顺序错误:
ConfigureServices先于ConfigureAppConfiguration执行,导致注册服务时KeyVault配置尚未加载 ConfigureServices内手动构建了不包含KeyVault的独立配置实例,无法读取密钥保管库中的内容
方案一:调整配置顺序,使用整合KeyVault的全局配置
将ConfigureAppConfiguration移至ConfigureServices之前,确保注册服务时应用配置已包含KeyVault的内容,同时直接使用Host提供的全局配置,而非手动构建新配置。
修改后的完整代码:
IHost host = Host.CreateDefaultBuilder(args) // 先配置应用配置,包含Azure KeyVault .ConfigureAppConfiguration((context, config) => { if (context.HostingEnvironment.IsDevelopment() || context.HostingEnvironment.IsProduction()) { var root = config.Build(); using var x509Store = new X509Store(StoreLocation.CurrentUser); x509Store.Open(OpenFlags.ReadOnly); var x509Certificate = x509Store.Certificates .Find( X509FindType.FindByThumbprint, root["AzureADCertThumbprint"], validOnly: false) .OfType<X509Certificate2>() .Single(); config.AddAzureKeyVault( new Uri($"https://{root["KeyVaultName"]}.vault.azure.net/"), new ClientCertificateCredential( root["AzureADDirectoryId"], root["AzureADApplicationId"], x509Certificate)); } }) // 注册服务时直接使用已包含KeyVault的全局配置 .ConfigureServices((context, services) => { var configuration = context.Configuration; // 配置Application Insights var aiOptions = new ApplicationInsightsServiceOptions(); aiOptions.ConnectionString = configuration["APPINSIGHTS_CONNECTIONSTRING"]; aiOptions.EnableQuickPulseMetricStream = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableQuickPulseMetricStream"); aiOptions.EnableEventCounterCollectionModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableEventCounterCollectionModule"); aiOptions.EnableAppServicesHeartbeatTelemetryModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableAppServicesHeartbeatTelemetryModule"); aiOptions.EnableAzureInstanceMetadataTelemetryModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableAzureInstanceMetadataTelemetryModule"); aiOptions.EnableDependencyTrackingTelemetryModule = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableDependencyTrackingTelemetryModule"); aiOptions.EnableAdaptiveSampling = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableAdaptiveSampling"); aiOptions.EnableHeartbeat = configuration.GetSection("ApplicationInsights").GetValue<bool>("EnableHeartbeat"); aiOptions.AddAutoCollectedMetricExtractor = configuration.GetSection("ApplicationInsights").GetValue<bool>("AddAutoCollectedMetricExtractor"); services.AddApplicationInsightsTelemetryWorkerService(aiOptions); // ------------------------ // ----- Lite DB START----- // ------------------------ // 直接从全局配置读取KeyVault中的连接字符串 var connectionString = configuration.GetSection("LiteDB").GetValue<string>("ConnectionString"); services.AddSingleton<ILiteDatabase, LiteDatabase>(x => new LiteDatabase(connectionString)); // ----------------------- // ----- Lite DB END----- // ----------------------- services.AddTransient<ILogExtension, LogExtension>(); services.AddHostedService<AzureSignalRService>(); }) .Build();
方案二:延迟解析配置(适用于无法调整顺序的场景)
如果因特殊原因无法调整配置构建顺序,可通过IServiceProvider延迟获取已加载KeyVault的配置:
在ConfigureServices中替换LiteDB的注册代码:
// 延迟从服务容器中获取完整配置 services.AddSingleton<ILiteDatabase, LiteDatabase>(sp => { var configuration = sp.GetRequiredService<IConfiguration>(); var connectionString = configuration.GetSection("LiteDB").GetValue<string>("ConnectionString"); return new LiteDatabase(connectionString); });
额外注意事项
- 确保KeyVault中已创建对应路径的密钥:例如
LiteDB:ConnectionString(配置层级用冒号分隔) - 验证用于认证的Azure AD应用拥有KeyVault的
Secret Get权限
内容的提问来源于stack exchange,提问作者OJB1
相关产品推荐
相关产品推荐

