【问题标题】:How do you encrypt a password within appsettings.json for ASP.net Core 2?如何在 ASP.net Core 2 的 appsettings.json 中加密密码?
【发布时间】:2018-01-08 22:56:38
【问题描述】:

我想使用我的 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

我的做法是正确的还是有更好的做法?

【问题讨论】:

  • 以前因为托管 Internet 信息系统而工作,现在它充当反向代理,或者您使用 HttpSys。您可能能够加密文件,然后在发出请求时,应用程序将解密。不过,我觉得这可能存在一些主要的性能问题。
  • 只需使用bouncy castle 和PKCS 密码和证书,并将证书存储在环境中。例如。

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


【解决方案1】:

请记住,不要将机密存储在网站中的主要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) 中看到,我在其中详细描述了使用桥接模式。 Github 上还有一个完整的示例(包括一个解密类)https://github.com/configureappio/ConfiguarationBridgeCrypto

【讨论】:

    【解决方案2】:

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

    也就是说,Core 的部分优点在于它是完全模块化的。您始终可以创建自己的配置提供程序并实现您想要的任何内容。例如,您可以编写一个实际上确实支持加密的 JSON 提供程序,如果你想这样做的话。

    【讨论】:

    • 如果我想推出自己的配置提供程序,我应该将密码存储在哪里?我想我会将它存储为环境变量,但一定有更好的方法,不是吗?
    • 这就是重点:您可以将它存储在您喜欢的任何地方。配置提供程序本质上只是知道如何从特定源读取的东西。例如,JSON 提供者知道如何从 JSON 中读取值。您缺少的唯一难题是“知道如何读取加密值”,默认 JSON 提供程序不知道。这只是您必须添加到 您的 提供程序的逻辑,但源可以是 JSON、环境变量、Web.config 等。任何最适合您的。
    • 将 Azure KeyVault 的 ClientSecret 存储在哪里? documentation 声明此 ClientSecret 存储在 appsettings.json 中。我认为这也是非常不可取的,这样做是为了让示例易于理解。
    • @Chris Pratt 我想从不在 Azure 上托管的 .NET 核心应用程序访问 Azure KeyVault,解决此问题的最佳方法是什么?所有 MS 文档都暗示该应用程序托管在 Azure 中。
    【解决方案3】:

    对于 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 文件中的密码。您可以使用内置 Key-per-file Configuration Provider 或自定义配置提供程序从 docker secret 中读取密码并将其映射到配置值。

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

    【讨论】:

      【解决方案4】:

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

      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
          },
      

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 我对 Secret Manager 的唯一问题是该工具的开发人员清楚地将其标记为仅供开发使用。我想在生产和开发中使用相同的工具。 Secret Manager 工具不会创建加密的 JSON。
        • > 环境变量通常以纯文本形式存储。如果机器或进程受到威胁,不受信任的各方可以访问环境变量。可能需要采取额外措施来防止泄露用户机密。 > Secret Manager 工具不会对存储的秘密进行加密,不应将其视为受信任的存储。它仅用于开发目的。键和值存储在用户配置文件目录中的 JSON 配置文件中。
        • 我明白你的意思,我同意。您对安全方面的使用有何建议?
        猜你喜欢
        • 1970-01-01
        • 2020-05-08
        • 2017-08-12
        • 2020-10-14
        • 2013-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-02
        相关资源
        最近更新 更多