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

如何在ASP.Net Core中加密/解密appsettings.json的连接字符串?

ASP.NET Core Web API 连接字符串加密问题

我正在开发ASP.NET Core Web API,开发环境中直接在appsettings.json里用明文写连接字符串。现在要把API发布到生产服务器和外网(使用FortiWeb而非Azure),不能再明文保存凭据。我找了很多加密方法,大多依赖Azure Key Vault或用户机密,最后打算采用某篇文章的方案,但文章内容不完整。我已经创建了文中的类,但不知道怎么实际使用。这是我第一次从零开发API,完全不懂信息安全。


已完成的代码文件

appsettings.json

{
  "ConnectionStrings": {
    "MyConnection": "Data Source=MyServerName;Initial Catalog=MyDb;Persist Security Info=True;User ID=MyUser;Password=MyPwd"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

DecryptedConfiguration.cs

public class DecryptedConfiguration : ConfigurationProvider
{
    public ICryptoTransform Decryptor;
    private ICryptoTransform Encryptor;

    internal DecryptedConfiguration(byte[] Key, byte[] IV)
    {
        Aes aes = Aes.Create();
        Decryptor = aes.CreateDecryptor(Key, IV);
        Decryptor = aes.CreateDecryptor(Key, IV);
    }

    public override bool TryGet(string key, out string value)
    {
        if (base.TryGet(key, out value))
        {
            byte[] decryptedBytes = Convert.FromBase64String(value);
            byte[] textBytes = Decryptor.TransformFinalBlock(decryptedBytes, 0, decryptedBytes.Length);
            value = Encoding.Unicode.GetString(textBytes);
            return true;
        }
        return false;
    }

    public override void Set(string key, string value)
    {
        byte[] textBytes = Encoding.Unicode.GetBytes(value);
        byte[] decryptedBytes = Decryptor.TransformFinalBlock(textBytes, 0, textBytes.Length);
        base.Set(key, Convert.ToBase64String(decryptedBytes));
    }
}

DecryptedConfigurationSource.cs

public class DecryptedConfigurationSource : IConfigurationSource
{
    private byte[] Key;
    private byte[] IV;

    public DecryptedConfigurationSource(byte[] Key, byte[] IV)
    {
        this.Key = Key;
        this.IV = IV;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new DecryptedConfiguration(Key, IV);
    }
}

Startup.cs(Configure方法片段)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    Aes aes = Aes.Create();
    byte[] key = aes.Key;
    byte[] iv = aes.IV;

    IConfigurationBuilder encryptingBuilder = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json")
        .Add(new DecryptedConfigurationSource(key, iv))
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
    IConfiguration cfg = encryptingBuilder.Build();

    string ecryptedValue = cfg.GetValue<string>("ConnectionStrings:MyConnection");
}

完整使用步骤

1. 修复DecryptedConfiguration类的错误

你的代码存在两处关键错误,先修正:

  • 构造函数重复赋值Decryptor,需同时初始化加密器
  • Set方法误用解密器,应该用加密器处理明文

修正后的代码:

public class DecryptedConfiguration : ConfigurationProvider
{
    private readonly ICryptoTransform _decryptor;
    private readonly ICryptoTransform _encryptor;

    internal DecryptedConfiguration(byte[] key, byte[] iv)
    {
        using Aes aes = Aes.Create();
        _encryptor = aes.CreateEncryptor(key, iv);
        _decryptor = aes.CreateDecryptor(key, iv);
    }

    public override bool TryGet(string key, out string value)
    {
        if (base.TryGet(key, out value))
        {
            byte[] encryptedBytes = Convert.FromBase64String(value);
            byte[] textBytes = _decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            value = Encoding.Unicode.GetString(textBytes);
            return true;
        }
        return false;
    }

    public override void Set(string key, string value)
    {
        byte[] textBytes = Encoding.Unicode.GetBytes(value);
        byte[] encryptedBytes = _encryptor.TransformFinalBlock(textBytes, 0, textBytes.Length);
        base.Set(key, Convert.ToBase64String(encryptedBytes));
    }
}

2. 生成加密后的连接字符串

先把明文连接字符串加密,替换appsettings.json中的明文值。可以写一个临时工具生成加密值:

public static string EncryptConnectionString(string plainText, byte[] key, byte[] iv)
{
    using Aes aes = Aes.Create();
    using ICryptoTransform encryptor = aes.CreateEncryptor(key, iv);
    byte[] textBytes = Encoding.Unicode.GetBytes(plainText);
    byte[] encryptedBytes = encryptor.TransformFinalBlock(textBytes, 0, textBytes.Length);
    return Convert.ToBase64String(encryptedBytes);
}

运行后得到加密字符串,更新appsettings.json:

"ConnectionStrings": {
  "MyConnection": "替换为加密后的Base64字符串"
}

3. 正确集成配置到应用

不要在Configure方法中单独构建配置,应该在启动时将自定义配置源加入主配置体系,让整个应用能直接获取解密后的值。

.NET 6+ Program.cs示例

var builder = WebApplication.CreateBuilder(args);

// 从环境变量加载密钥和IV(生产环境禁止硬编码)
byte[] key = Convert.FromBase64String(Environment.GetEnvironmentVariable("AES_KEY"));
byte[] iv = Convert.FromBase64String(Environment.GetEnvironmentVariable("AES_IV"));

// 添加自定义配置源
builder.Configuration.Add(new DecryptedConfigurationSource(key, iv));

// 注册数据库上下文
builder.Services.AddDbContext<MyDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("MyConnection")));

var app = builder.Build();

// 中间件配置...
app.Run();

.NET 5及以前 Startup.cs示例

public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
    var configBuilder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();

    // 加载密钥和IV
    byte[] key = Convert.FromBase64String(Environment.GetEnvironmentVariable("AES_KEY"));
    byte[] iv = Convert.FromBase64String(Environment.GetEnvironmentVariable("AES_IV"));
    configBuilder.Add(new DecryptedConfigurationSource(key, iv));

    Configuration = configBuilder.Build();
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<MyDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("MyConnection")));
    // 其他服务注册...
}

4. 生产环境密钥管理注意事项

  • 禁止硬编码密钥和IV,通过服务器环境变量、权限受限的本地文件或硬件安全模块(HSM)获取
  • 确保生产服务器上只有应用进程能访问密钥存储位置
  • 定期轮换密钥,避免密钥泄露导致所有加密数据暴露

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:27:17