Azure Key Vault是微软云平台提供的集中式密钥管理服务,可以安全地存储数据库连接字符串、API密钥、证书和加密密钥。对C#开发者来说,把敏感信息从appsettings.json迁到Key Vault,再配合托管标识(Managed Identity),可以彻底避免在代码和配置文件中出现明文凭据。本文完整演示从零搭建到代码访问的全过程。

一、创建Key Vault并配置访问权限
登录Azure门户后,搜索Key Vault服务,点击创建。资源组和实例名称按项目规范填写,区域建议选择与应用服务相同的区域以降低延迟。定价层方面,标准版对于绝大多数场景已经足够,高级版主要多了HSM硬件加密模块的支持。
创建完成后,进入左侧菜单的“访问控制(IAM)”,基于角色的访问控制(RBAC)是当前官方推荐的方式。给当前用于开发的Azure账号分配“Key Vault Secrets User”角色,作用范围限定在该实例上。这样本地开发时你的账号就能读取和列出Secret。生产环境则建议在“访问策略”或RBAC中给应用服务的托管标识授权,而不是使用客户端密钥。
接着通过界面或CLI写入一个测试密钥。用CLI的方式更方便后续脚本化:
az keyvault create --name myapp-kv-demo --resource-group myrg --location eastasia az keyvault secret set --vault-name myapp-kv-demo --name DbConnectionString --value "Server=xxx;Database=MyDb;"
二、安装SDK并使用DefaultAzureCredential认证
在项目中通过NuGet安装官方客户端库。核心包有两个:Azure.Security.KeyVault.Secrets负责Secret的读写,Azure.Identity负责身份认证。安装命令如下:
dotnet add package Azure.Security.KeyVault.Secrets dotnet add package Azure.Identity
认证环节推荐使用DefaultAzureCredential。它的好处是按顺序尝试多种凭据方式:在Azure上运行时会自动使用托管标识,本地开发时会使用Visual Studio登录账号或者Azure CLI登录状态,一套代码同时兼容本地和生产环境,不需要写if-else判断运行环境。
初始化客户端的代码非常简洁,注意vault地址要带https前缀:
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
var credential = new DefaultAzureCredential();
var client = new SecretClient(
new Uri("https://myapp-kv-demo.vault.azure.net/"),
credential);
KeyVaultSecret secret = await client.GetSecretAsync("DbConnectionString");
string connStr = secret.Value;
Console.WriteLine("成功读取连接字符串");第一次本地运行前,需要先执行az login确保CLI处于登录状态,否则DefaultAzureCredential会抛出CredentialUnavailableException。如果用的是Visual Studio,也可以在“工具-选项-Azure服务身份验证”里配置账号,优先级会高于CLI。
三、集成到ASP.NET Core配置系统
直接调用SecretClient虽然可行,但更优雅的做法是把Key Vault接入 IConfiguration。这样所有依赖IConfiguration的代码无需任何改动,迁移成本几乎为零。
在Program.cs中添加Key Vault配置源:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddAzureKeyVault(
new Uri("https://myapp-kv-demo.vault.azure.net/"),
new DefaultAzureCredential());
var app = builder.Build();
app.MapGet("/", (IConfiguration config) =>
{
// 读取Key Vault中的Secret,用法与普通配置一致
var conn = config["DbConnectionString"];
return $"读取到配置,长度: {conn?.Length}";
});
app.Run();使用这种方式要注意命名映射规则:Key Vault的Secret名称中不允许出现冒号,双下划线会被自动转换为配置节的冒号。例如Secret名为ConnectionStrings__Default,代码里用config["ConnectionStrings:Default"]即可读取。
还有一个性能细节值得注意:Key Vault的调用虽然走缓存,配置系统在启动时会拉取一次Secret,运行期间不会反复请求,但如果你的Secret更新频繁,就需要自己实现刷新逻辑或者重启应用。Key Vault本身也有限流,单实例每十秒约4000次操作,设计时要避免高频循环读取。
四、异常处理与生产环境建议
访问Key Vault可能因为网络问题、权限不足或者限流而失败,这些异常不应该让应用裸奔。常见的做法是在启动时做一次健康检查,失败则快速失败并输出明确日志:
try
{
var secret = await client.GetSecretAsync("DbConnectionString");
}
catch (Azure.RequestFailedException ex) when (ex.Status == 403)
{
// 403通常是权限问题,检查托管标识是否分配了Secrets User角色
_logger.LogError(ex, "Key Vault访问被拒绝,请检查RBAC角色分配");
throw;
}
catch (Azure.RequestFailedException ex) when (ex.Status == 429)
{
// 触发限流,建议增加重试策略
_logger.LogWarning("Key Vault请求被限流");
throw;
}生产部署时,把应用发布到App Service后,在“设置-标识”里打开系统分配的托管标识,然后到Key Vault的访问控制中给这个标识分配角色。整个过程不需要生成任何客户端密钥,也没有凭据轮换的负担,这是托管标识相对Service Principal最大的优势。
最后补充几点实践建议:密钥轮换时Key Vault会保留历史版本,可以通过GetSecretVersionsAsync追溯;敏感值不要在日志中输出Secret.Value;如果合规要求高,可以开启Key Vault的软删除和清除保护功能,防止误删除导致的事故。按照这套流程落地后,你的C#应用就实现了密钥与代码的彻底分离,安全性会有明显提升。
C#Azure Key Vault.NET修改时间:2026-09-15 00:26:33