繁体   English   中英

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

[英]How to encrypt/decrypt connection string in appsettings.json?

我正在开发一个 ASP.Net Core Web API ,而在开发环境中,我们只需在appsettings.json文件中以纯文本形式编写连接字符串。 但是现在我们要将此 API 发布到我们的生产服务器和 web(我们将使用 FortiWeb 发布 API,而不是 Azure),所以我们不能再拥有纯文本的用户凭据。

我一直在寻找保护/加密连接字符串的方法,但大多数解决方案都使用 Azure Key Vault 或用户机密。 我决定按照这篇文章来加密和解密appsettings.json信息,但它有点不完整。 我设法创建了文章中描述的类,但我被卡住了,不知道如何使用它。 这是我第一次完全从头开始开发 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 class 上:

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 class 上:

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 class 上:

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");
}

作为一个简短的提示,我可以建议将值存储在环境变量中。 这比将它们直接存储在文本文件中更安全一些,因为访问环境变量需要比读取文件更高的权限。 对于许多公司来说,如果 azure 密钥保管库或 aws 机密管理器无法使用,这已经足够了。 如果您将应用程序托管为 docker 容器或在 VM 上运行,则可以同时使用环境变量。 这里有一些关于易于使用的解决方案的文章,尽管生产文章建议使用 azure 密钥库https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0 &tabs=窗口

作为替代方案,您可以考虑使用文章中描述的 Secret manager 提供程序。

我不建议按照文章的建议进行,因为这涉及将加密密钥永久存储在某处(文章提到您不应该调用 Aes aes = Aes.Create(); 因为每次调用它都会生成新密钥,您需要一个永久的一)。 但是要确保它的安全,您必须从诸如 azure 密钥库之类的安全的东西中加载它,如果您在代码中拥有它,那么有人可以下载您的程序集,反编译它,访问存储的密钥并可以自行解密您的所有秘密。 如果我的理解是正确的,那么文章中提出的解决方案是“通过默默无闻的安全”而不是实际的解决方案 - 它只会使访问秘密变得更加困难,但仍然可以完全管理,就像您将秘密放在 appsettings.json 中一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM