如何使用.NET Core的ConfigurationBuilder获取Azure KeyVault的加密密钥和证书
问题解答
默认的AddAzureKeyVault配置扩展仅支持拉取Azure Key Vault中的机密(Secrets),原生不支持直接拉取*密钥(Keys)*和证书对象,这是因为.NET配置系统的定位是存储字符串类型的键值对,而Keys是用于加解密/签名的结构化加密对象、证书包含公私钥等多维度信息,和普通配置的应用场景不匹配。
实现需求的两种方案
方案1:自定义配置源,实现同时拉取Keys/证书/机密
如果需要将Keys或证书的指定内容(比如公钥PEM、证书指纹等)也加载到IConfiguration中,并且自定义查询优先级,可以通过自定义配置源实现:
- 首先引入最新的Azure Key Vault SDK包:
Azure.Security.KeyVault.Keys、Azure.Security.KeyVault.Certificates、Azure.Identity,你原本使用的旧版Microsoft.Azure.KeyVaultSDK已停止维护,也可以按照相同逻辑扩展,但更建议迁移到新版SDK - 自定义配置提供者,在加载时同时调用KeyClient、CertificateClient拉取对应内容,按照你需要的优先级写入配置字典
示例核心代码如下:
// 自定义Key Vault配置源 public class CustomKeyVaultConfigurationSource : IConfigurationSource { public Uri KeyVaultUri { get; set; } public TokenCredential Credential { get; set; } // 可自定义加载顺序,后加载的内容优先级更高,会覆盖同键名的前置内容 public int LoadOrder { get; set; } = 3; public IConfigurationProvider Build(IConfigurationBuilder builder) { return new CustomKeyVaultConfigurationProvider(KeyVaultUri, Credential); } } // 自定义配置提供者 public class CustomKeyVaultConfigurationProvider : ConfigurationProvider { private readonly KeyClient _keyClient; private readonly SecretClient _secretClient; private readonly CertificateClient _certClient; public CustomKeyVaultConfigurationProvider(Uri kvUri, TokenCredential credential) { _keyClient = new KeyClient(kvUri, credential); _secretClient = new SecretClient(kvUri, credential); _certClient = new CertificateClient(kvUri, credential); } public override void Load() { var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // 先加载Secrets,优先级最低 foreach (var secret in _secretClient.GetPropertiesOfSecrets()) { if (secret.Enabled != true) continue; var secretVal = _secretClient.GetSecret(secret.Name).Value; // 键名转换规则和官方默认保持一致:用--替换配置键的:,适配Key Vault命名规范 var configKey = secret.Name.Replace("--", ":"); data[configKey] = secretVal.Value; } // 再加载证书,优先级高于Secrets,示例存储证书公钥的Base64编码 foreach (var cert in _certClient.GetPropertiesOfCertificates()) { if (cert.Enabled != true) continue; var certVal = _certClient.GetCertificate(cert.Name).Value; var configKey = cert.Name.Replace("--", ":"); data[configKey] = Convert.ToBase64String(certVal.Cer); } // 最后加载Keys,优先级最高,示例存储公钥字符串 foreach (var key in _keyClient.GetPropertiesOfKeys()) { if (key.Enabled != true) continue; var keyVal = _keyClient.GetKey(key.Name).Value; var configKey = key.Name.Replace("--", ":"); data[configKey] = keyVal.Key.ToString(); } Data = data; } }
之后在配置构建器中注册自定义源即可:
.ConfigureAppConfiguration((context, configBuilder) => { // 移除默认的KeyVault源,改用自定义源 configBuilder.Sources.RemoveAll(s => s is AzureKeyVaultConfigurationSource); configBuilder.Add(new CustomKeyVaultConfigurationSource { KeyVaultUri = new Uri(keyvaultUrl), Credential = new DefaultAzureCredential() }); })
完成配置后就可以直接通过_configuration["Blobs:Users:Key"]读取到优先级最高的对应内容。
方案2:直接注入Key/Certificate客户端单独查询
如果不需要把Keys/证书作为全局配置加载,更推荐这种方式:不需要修改配置源,直接在需要使用加密密钥/证书的地方注入对应客户端单独查询,性能更高,也符合Key Vault的最佳使用实践:
// 注册客户端到DI容器 builder.Services.AddSingleton(new KeyClient(new Uri(keyvaultUrl), new DefaultAzureCredential())); builder.Services.AddSingleton(new CertificateClient(new Uri(keyvaultUrl), new DefaultAzureCredential()));
使用时直接注入调用:
public HelperClass(KeyClient keyClient, ILogger<HelperClass> logger) { // 直接查询指定加密密钥 var key = keyClient.GetKey("Blobs--Users--Key").Value; // 可直接用返回的Key对象做加解密/签名操作 }
额外注意事项
- Key Vault中导入证书时,默认会自动生成一个同名的机密,存储证书PFX的Base64编码,如果只是需要用到证书的完整内容,直接读取同名机密即可,不需要额外扩展
- 不可导出类型的Key无法获取私钥内容,只能拿到公钥用于验签/加密操作,如果需要用到私钥,建议用证书存储的方式处理
内容的提问来源于stack exchange,提问作者sargeMonkey
相关产品推荐
相关产品推荐

