Asp.net core 在ASP.NET内核中存储生产机密
我试图找出在哪里最好地存储ASP.NET核心应用程序的应用程序生产机密。有两个类似的问题 和 两者都建议使用环境变量 我的问题是,我想用不同的数据库和不同的数据库凭据运行我的web应用程序的多个实例。所以应该有一些每个实例的配置,包括秘密 如何以安全的方式实现这一点 请注意,应用程序应该能够自我托管,并且可以在IIS下托管!(稍后我们还计划在Linux上运行它,如果这对这个问题很重要的话) 更新Asp.net core 在ASP.NET内核中存储生产机密,asp.net-core,Asp.net Core,我试图找出在哪里最好地存储ASP.NET核心应用程序的应用程序生产机密。有两个类似的问题 和 两者都建议使用环境变量 我的问题是,我想用不同的数据库和不同的数据库凭据运行我的web应用程序的多个实例。所以应该有一些每个实例的配置,包括秘密 如何以安全的方式实现这一点 请注意,应用程序应该能够自我托管,并且可以在IIS下托管!(稍后我们还计划在Linux上运行它,如果这对这个问题很重要的话) 更新 这个问题不是关于尝试在生产中使用ASP.NET用户机密!用户机密不适用于生产。正如它们所述,用户机密
这个问题不是关于尝试在生产中使用ASP.NET用户机密!用户机密不适用于生产。正如它们所述,用户机密仅用于开发(以避免将凭据意外提交给SCM),不适用于生产。每个数据库应使用一个连接字符串,即
连接字符串:CmsDatabaseProduction
,连接字符串:CmsDatabaseDevelopment
,等等
或者使用docker容器(当您不使用Azure应用程序服务时),然后您可以根据每个容器进行设置
或者,也可以使用基于环境的appsetting文件appsettings.production.json,但它们不能包含在源代码管理(Git、CSV、TFS)中
在启动过程中,只需执行以下操作:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
这样,您就可以从appsettings.production.json中加载特定的内容,并且仍然可以通过环境变量覆盖它 除了使用Azure应用程序服务或docker容器外,您还可以使用IDataProtector
在生产中安全地存储应用程序机密:
通过运行应用程序的-config开关输入应用程序机密,例如:dotnet helloworld-config
;在Program.Main
中,检测此开关以允许用户输入机密并存储在单独的.json文件中,加密:
公共类程序
{
专用常量字符串APP_NAME=“5E71EE95-49BD-40A9-81CD-B1DFD873EEA8”;
private const string SECRET\u CONFIG\u FILE\u NAME=“appsettings.SECRET.json”;
公共静态void Main(字符串[]args)
{
如果(args!=null&&args.Length==1&&args[0]。ToLowerInvariant()==“-config”)
{
ConfigAppSettingsCret();
返回;
}
CreateWebHostBuilder(args.Build().Run();
}
公共静态IWebHostBuilder CreateWebHostBuilder(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((生成器,选项)=>
{
AddJsonFile(ConfigFileFullPath,可选:true,reloadOnChange:false);
})
.UseStartup();
内部静态IDataProtector GetDataProtector()
{
var servicecolection=新servicecolection();
serviceCollection.AddDataProtection()
.SetApplicationName(应用程序ID)
.PersistKeySystem(新目录信息(SecretsDirectory));
var services=serviceCollection.BuildServiceProvider();
var dataProtectionProvider=services.GetService();
返回dataProtectionProvider.CreateProtector(应用程序ID);
}
私有静态无效ConfigAppSettingsCret()
{
var-protector=GetDataProtector();
字符串dbPassword=protector.Protect(“dbPassword”,ReadPasswordFromConsole());
……其他秘密
字符串json=…;//将加密的秘密序列化为json
var path=ConfigFileFullPath;
WriteAllText(路径,json);
Console.WriteLine($“将应用程序设置机密写入${path}”已成功完成。”);
}
私有静态字符串目录
{
获取{return Directory.GetParent(typeof(Program).Assembly.Location.FullName;}
}
私有静态字符串ConfigFileFullPath
{
获取{return Path.Combine(CurrentDirectory,SECRET_CONFIG_FILE_NAME);}
}
}
在Startup.cs中,读取并解密密码:
public void配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
...
if(env.IsProduction())
{
var protector=Program.GetDataProtector();
var builder=new-SqlConnectionStringBuilder();
builder.Password=protector.Unprotect(配置[“DbPassword”]);
...
}
}
顺便说一句,appsettings.production.json
或环境变量实际上不是一个选项。顾名思义,机密永远不应该以纯文本形式存储。我知道在开发期间用户机密存在问题。但这不是问题所在,我只是在谈论生产时间!环境设置文件没有帮助,因为它对于生产中的每个实例仍然是相同的,并且覆盖环境变量对于所有实例仍然是相同的!我现在对Docker还不够了解,但也许这个想法会有所帮助。@NicolasR:不一定。每个安装将有一个application.production.json。如果您的应用程序位于3个不同的文件夹中,您可以将它们的applciation.production.json'设置为所需的值。您只需确保从源代码管理中排除
application.production.json',因为它现在包含敏感数据。还有
Microsoft.Extensions.Configuration.CommandLine,它可以从命令行参数读取配置,但是在ASP.NET内核中使用它并不容易,因为您在Startup类中构建了配置,并且您不容易从这里访问传递到Main的args
参数method@NicolasR:嗯,据我所知,没有“安全字符串”就像传统ASP.NET应用程序中的一个,您可以将加密字符串放入web.config并在运行时对其进行解密,因此除非您编写