Gab*_*bic 6 c# security encryption asp.net-core asp.net-core-webapi
我正在开发 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": "*"
}
Run Code Online (Sandbox Code Playgroud)
上课时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));
}
}
Run Code Online (Sandbox Code Playgroud)
上课时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);
}
}
Run Code Online (Sandbox Code Playgroud)
上课时Startup.cs:
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");
}
Run Code Online (Sandbox Code Playgroud)
作为一个简短的提示,我建议将值存储在环境变量中。这比将它们简单地存储在文本文件中更安全,因为访问环境变量比读取文件需要更高的权限。对于许多公司来说,如果无法使用 azure key Vault 或 aws Secret Manager,这已经足够了。如果您将应用程序托管为 docker 容器或在虚拟机上运行,则可以使用这两种环境变量。这里有一些关于易于使用的解决方案的文章,尽管生产文章建议使用 azure key Vault https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0 &选项卡=窗口
作为替代方案,您可以考虑使用本文中描述的 Secret 管理器提供程序。
我不建议按照文章建议的方式进行操作,因为这涉及在某个地方永久存储加密密钥(文章提到您不应该调用 Aes aes = Aes.Create(); 因为每次调用它时都会生成新密钥,您将需要一个永久的密钥一)。但是要确保它的安全,您必须从像天蓝色密钥库这样安全的东西加载它,如果您在代码中拥有它,那么有人可以下载您的程序集,反编译它,访问存储的密钥,并可以自行解密您的所有秘密。如果我的理解是正确的,那么本文中提出的解决方案是“通过模糊实现安全性”而不是实际的解决方案 - 它只会使访问机密变得更加困难,但仍然完全可以管理,就像您将机密放在 appsettings.json 中一样。
| 归档时间: |
|
| 查看次数: |
20771 次 |
| 最近记录: |