如何在appsettings.json中为ASP.net Core 2加密密码?

时间:2018-01-08 22:56:39

标签: c# asp.net encryption asp.net-core-mvc asp.net-core-2.0

我想使用我的appsettings.json存储“主密码”。

然后,此主密码将用于打开由此优秀密码存储包生成的私钥(及其后续密码存储区):https://github.com/neosmart/SecureStore

问题是,我想不出有什么方法可以加密主密码。我知道在.NET 4.5中,可以执行以下操作:

1)将您的密码放入web.config文件

2)运行此脚本:aspnet_regiis.exe -pef appSettings“C:\ myfolder”

3)您的密码最终会被加密 - 但您的程序会安全阅读。

https://www.codeproject.com/Articles/599416/Encrypting-ASP-NET-Application-Settings

我是以正确的方式做到这一点还是有更好的做法?

5 个答案:

答案 0 :(得分:4)

JSON配置提供程序不支持加密。目前,唯一支持加密配置的开箱即用服务提供商是Azure KeyVault。无论您的应用程序是否实际托管在Azure上,您都可以使用KeyVault,虽然它不是免费的,但在大多数情况下,这些许可可能只会花费几美分。

那就是说,Core的一部分美妙之处在于它完全是模块化的。您始终可以创建自己的配置提供程序并实现您想要的任何内容。例如,您可以编写一个实际 支持加密的JSON提供程序,如果这是您想要的方式。

答案 1 :(得分:2)

请记住,不要将秘密存储在网站中的主appsettings.json中,并且通常保存在源代码管理中。使用文件提供程序在服务器上的其他位置找到该文件。

如果您有权访问Azure,则可以将密码存储在Azure Key Vault而不是appsettings.json

考虑到这一点,如果您想使用JSON文件,可以使用桥接器或代理类来处理值的解密。

首先,您需要一个类来解密这些值。为简洁起见,我不会在此处详细介绍解密类,并假设已经编写了一个名为SettingsDecryptor的类,并使用单个方法Decrypt实现了一个名为ISettingsDecryptor的接口,该方法解密了字符串值。

桥类有两个构造函数参数。

  • 第一个是IOptions<T>IOptionsSnapshot<T>,其中T是appsettings.json中的部分通过services.Configure方法绑定的类(例如MyAppSettings )。或者,如果您不想绑定到类,则可以使用IConfiguration代替直接从配置中读取。
  • 第二个是实现ISettingsDecryptor的解密类。

在桥类中,需要解密的每个属性都应该使用解密类来解密配置中的加密值。

public class MyAppSettingsBridge : IAppSettings
{
    private readonly IOptions<MyAppSettings> _appSettings;

    private readonly ISettingsDecrypt _decryptor;

    public MyAppSettingsBridge(IOptionsSnapshot<MyAppSettings> appSettings, ISettingsDecrypt decryptor) {
        _appSettings = appSettings ?? throw new ArgumentNullException(nameof(appSettings));
        _decryptor = decryptor ?? throw new ArgumentException(nameof(decryptor));
    }

    public string ApplicationName => _appSettings.Value.ApplicationName;

    public string SqlConnectionSting => _decryptor.Decrypt(_appSettings.Value.Sql);

    public string OracleConnectionSting => _decryptor.Decrypt(_appSettings.Value.Oracle);
}

DI容器应该设置如下:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddOptions();            
    services.Configure<MyAppSettings>(Configuration.GetSection("MyAppSettings"));
    services.AddSingleton(Configuration);        
    services.AddSingleton<ISettingsDecrypt, SettingsDecryptor>();
    services.AddScoped<IAppSettings, MyAppSettingsBridge>();
}

然后,控制器可以有一个构造函数,将桥接器作为IAppSettings来访问解密的设置。

上面的答案是整体解决方案的简要总结,因为需要相当多的代码。

完整的详细说明可以在我的博文Hiding Secrets in appsettings.json – Using a Bridge in your ASP.Net Core Configuration (Part 4)中看到,其中我详细介绍了使用桥接模式。在https://github.com/configureappio/ConfiguarationBridgeCrypto

上的Github上还有一个完整的例子(包括一个解密类)

答案 2 :(得分:1)

对于ASP.NET Core,最佳解决方案是在应用程序启动时对配置值进行任何转换,例如解密或字符串替换。这就是配置提供程序存在的原因。

可以将配置提供程序链接在一起。在Microsoft.Extensions.Configuration的源代码中,有一个名为ChainedConfigurationProvider的类可以用作示例。

GLFW_OPENGL_CORE_PROFILE

如果您使用的是Docker Swarm或Kubernetes,则无需加密appsettings.json文件中的密码。您可以使用内置的Key-per-file Configuration Provider或自定义配置提供程序从Docker机密读取密码并将其映射到配置值。

在我的博客文章How to manage passwords in ASP.NET Core configuration files上,我详细解释了如何创建自定义配置提供程序,该提供程序允许您仅将密码保密,并在运行时更新配置字符串。另外,本文的完整源代码也托管在github.com/gabihodoroaga/blog-app-secrets上。

答案 3 :(得分:1)

您可以看一下我的Moonrise.StandardUtils.NetStd NuGet软件包。 Settings类具有透明的加密/解密,并且是访问JSON设置文件(无论是Application还是User)的一种简单得多的方法。在任何.Net应用程序中。

Settings.Application.SettingsEncryptor = new DpApiSettingsEncryptor(DpApiSettingsEncryptor.ProtectionScope.Machine);
MyConfigClass config;
Settings.Application.Read("Configuration", ref config)

任何先前加密的个人或一组设置都将被解密。您可以使用以下方式加密设置:

Settings.Application.Write("ContainerStartup:FileProviders:BrandingConfig", secretValue, true);

或者使用捆绑在Moonrise.Microsoft.EncryptedJsonConfigurationMoonrise.Samples NuGet软件包中的EncryptAppSettings.exe-您将在软件包文件/目录中找到它-这是一种获取.exe文件的方法。民间。

Moonrise.Microsoft.EncryptedJsonConfiguration允许您将IConfigurationBuilder与.AddEncyptedJsonFile(...)一起使用,然后将透明解密使用EncryptAppSettings.exe加密的所有设置。

这是部分加密的appSettings.json的一部分

  "ContainerStartup": {
    "FileProviders": {
      "BrandingConfig": "[{ENC]{AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAsevacb5DdkaxvzOPPkLrdwQAAAACAAAAAAAQZgAAAAEAACAAAADITnvKp+Lnb5n6kPK7WyYuWFQLnbvbkOvgHBLBdIw2MAAAAAAOgAAAAAIAACAAAADqJZ0YUGC+jOEr4/6hgQ+8UdZ1ssbiEXXCjdhSV3teZ3AAAAAW4d8Z38JYNM1Dw45KquZYK+bTszYp/1wXt+LiYpiy2q88sOpQr5VpDFatgWar1aOePXA52RC6eZH1HFrYijqWTSEiffBqWzWZPPTXw1wkUVB5MLIjOq4bu33h+4Z23Vy+XaFsf6IFVl4ccM4fHpsRQAAAAAG5OP+nJQxzH3A7n3gnh8d2eAOFgLWzYCDgQon7NXHeEJcZezgxT+0npvIQ/kcYb1Xpwt7FiNtyJ2HZswL8MSg=]{ENC[{",
      "SearchingNotification": true,
      "UseBranding": false,
      "UseLocalModule": true,
      "UseLocalModuleEmbedded": true,
      "UseParentModules": true,
      "UseParentModulesEmbedded": false
    },

答案 4 :(得分:0)

您可以使用Secret Manager工具,而不是将敏感数据存储在您无法加密的json文件中。这是full documentation

编辑:从安全角度来看,它仅适用于开发目的。