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

11
我希望使用我的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

我这样做是正确的吗?还是有更好的方法?


1
以前可以工作是因为Internet Information System托管,现在它充当反向代理或者你使用HttpSys。你可以尝试加密文件,然后当请求到来时,应用程序会进行解密。但我觉得这可能会带来一些性能问题。 - Greg
1
只需使用Bouncy Castle和PKCS对密码进行加密,并将证书存储在环境中。例如。 - zaitsman
1
看看我在这里的回答是否有帮助:点击此处 - jamesSampica
相关阅读:https://gaevoy.com/2021/01/08/secure-your-appsettings-json.html - HackSlash
4个回答

12
记住不要将机密信息存储在网站中的主appsettings.json文件中,通常该文件保存在源代码控制中。使用文件提供程序,在服务器上的其他位置查找该文件。
如果您可以访问Azure,则可以将机密信息存储在Azure Key Vault中,而不是appsettings.json中。
考虑到这一点,如果您想使用JSON文件,可以使用桥接或代理类来处理值的解密。
首先,您需要一个类来解密值。为了简洁起见,我不会在此处详细介绍解密类,并假设已编写了一个名为SettingsDecryptor的类,并实现了一个名为ISettingsDecryptor的接口,其中包含一个单独的方法Decrypt,用于解密字符串值。
桥接类有两个构造函数参数:
第一个是IOptions<T>IOptionsSnapshot<T>,其中T是通过services.Configure方法绑定到appsettings.json部分的类(例如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容器应该像这样设置:

{{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,以访问解密后的设置。
上面的答案是对整体解决方案的简要概述,因为需要相当多的代码。
完整的详细说明可以在我的博客文章在ASP.Net Core配置中隐藏密码 - 使用桥接模式(第4部分)中看到,我在其中详细描述了使用桥接模式。 在Github上还有一个完整的示例(包括解密类)https://github.com/configureappio/ConfiguarationBridgeCrypto

6
JSON配置提供程序不支持加密。目前,唯一支持加密配置的开箱即用提供程序是Azure KeyVault。您可以使用KeyVault,无论您的应用程序是否实际托管在Azure上,尽管它不是免费的,但津贴通常只需花费几分钱。
话虽如此,Core的美妙之处在于它完全模块化。您始终可以创建自己的配置提供程序并实现您想要的任何内容。例如,如果您希望这样做,可以编写一个实际支持加密的JSON提供程序。

如果我想自己编写配置提供程序,我应该把密码存储在哪里?我想将其存储为环境变量,但肯定有更好的方法,对吧? - Ryan Battistone
1
这就是重点:您可以将其存储在任何地方。配置提供程序本质上只是知道如何从特定源读取的东西。例如,JSON提供程序知道如何从JSON中读取值。您缺少的唯一拼图是“知道如何读取加密值”,默认的JSON提供程序不具备此功能。这只是您需要添加到您的提供程序的逻辑,但源可以是JSON、环境变量、Web.config等。无论哪种方式最适合您。 - Chris Pratt
2
你会把Azure KeyVault的ClientSecret存放在哪里?文档指出,这个ClientSecret存储在appsettings.json文件中。我认为这也是不太理想的做法,只是为了让示例更容易理解。 - Fluous
3
@Chris Pratt 我想从一个没有托管在Azure上的.NET Core应用程序中访问Azure KeyVault,最好的方法是什么?所有的MS文档都暗示该应用程序是托管在Azure上的。 - Greg Quinn

2
对于ASP.NET Core,最好的解决方案是在应用程序启动时进行配置值的任何转换,例如解密或字符串替换。这就是为什么有配置提供程序存在的原因。
配置提供程序可以链接在一起。在Microsoft.Extensions.Configuration的源代码中,有一个名为ChainedConfigurationProvider的类,可以用作示例。
public static IHostBuilder CreateHostBuilder(string[] args)
{
    return new HostBuilder()
    .ConfigureAppConfiguration((host, config) => {

        var jsonFile = new ConfigurationBuilder();
        jsonFile.AddJsonFile("appsettings.json");
        // the json file is the source for the new configuration provider.
        config.AddConfiguration(jsonFile.Build());
    });
}

如果您正在使用Docker Swarm或Kubernetes,则无需在appsettings.json文件中加密密码。您可以使用内置的按键文件配置提供程序或自定义配置提供程序从Docker secret中读取密码,并将其映射到配置值。
在我的博客文章如何管理ASP.NET Core配置文件中的密码中,我详细解释了如何创建一个自定义配置提供程序,使您只需将密码保留为秘密并在运行时更新配置字符串。此外,本文的完整源代码托管在github.com/gabihodoroaga/blog-app-secrets上。

1
你可以查看我的Moonrise.StandardUtils.NetStd NuGet包。Settings类拥有透明的加密和解密功能,并且是访问JSON设置文件的更简单方法 - 无论是应用程序还是用户 - 在任何.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
    },

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接