.Net Core 是否支持每个环境的用户机密?

Joe*_*moe 6 visual-studio .net-core asp.net-core visual-studio-2019

假设我有指定的开发环境的appsettings.Development.json连接字符串和指定的登台环境的连接字符串appsettings.Staging.json

在开发和暂存之间切换我需要做的就是导航到项目属性中的 Visual Studio 调试选项卡并更改ASPNETCORE_ENVIRONMENT环境变量的值。

现在,appsettings.*.json出于安全原因,我当然不想有连接字符串。所以我把它移到了 User Secrets。

问题是 - 似乎secrets.json所有环境都使用一个文件。没有secrets.Development.jsonsecrets.Staging.json。这意味着在我通过 Visual Studio Debug 选项卡从 Development 切换到 Staging 环境之后,我还需要手动更改连接字符串,secrets.json这违背了为环境提供内置支持的目的。

在每个环境的基础上不支持用户机密是否正确?如果是这样 - 是否有另一种方法可以避免在切换环境时手动修改 Secret 连接字符串?

Pan*_*vos 21

如果您检查该工具的参数,dotnet user-secrets --help您会发现您可以为每个配置(调试、发布、任何其他您想要的)指定不同的秘密,但不能为每个环境指定不同的秘密。如果你仔细想想,这并不是一个糟糕的决定。

\n

环境ASPNETCORE_ENVIRONMENT变量旨在告诉您的应用程序当前计算机或容器是开发、生产还是其他环境,以便它可以选择适当的设置文件。此环境变量预计不会从一个应用程序执行到下一个应用程序执行发生更改。即使在使用容器时,环境变量也会从主机传递到容器,并且在容器的生命周期内不会发生更改。

\n

出于开发目的,这些secrets文件应该是针对每台计算机的,因此无需为每个环境保留单独的文件。使用单独的文件进行配置更有意义,允许开发人员简单地从开发更改为发布或测试或他们可能拥有的任何其他自定义配置。

\n

为每个配置指定秘密

\n

dotnet user-secrets工具的工作原理是从项目文件中读取UserSecretsId值并将机密存储在具有相同名称的 JSON 文件中,例如c952ecfc-344e-43e1-bb67-1ac05973d6c6.json. 可以UserSecretsId为每个配置存储一个。

\n
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">\n    <UserSecretsId>c952ecfc-344e-43e1-bb67-1ac05973d6c6</UserSecretsId>\n</PropertyGroup>\n<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">\n    <UserSecretsId>7D104000-2230-4EDE-8AE6-63BDDA0BD0C5</UserSecretsId>\n</PropertyGroup>\n
Run Code Online (Sandbox Code Playgroud)\n

-c参数用于指定配置时,该user-secrets工具将从UserSecretsId相应部分读取值并使用它来存储或读取机密。

\n

dotnet user-secrets init命令无法识别该-c参数,因此csproj需要直接修改该文件。

\n

完成后,可以通过指定配置来设置和读取机密,例如:

\n
\xe2\x9d\xaf dotnet user-secrets set -c Debug Key1 Value1\nSuccessfully saved Key1 = Value1 to the secret store.\n\n\xe2\x9d\xaf dotnet user-secrets set -c Release Key1 Value2\nSuccessfully saved Key1 = Value2 to the secret store.\n\n\xe2\x9d\xaf dotnet user-secrets list -c Debug\nKey1 = Value1\n\n\xe2\x9d\xaf dotnet user-secrets list -c Release\nKey1 = Value2\n
Run Code Online (Sandbox Code Playgroud)\n


Jan*_*sky 14

我也需要这个,我想我已经想出了一个优雅的解决方案。

secrets.json文件在您正在使用的所有环境之间共享,您可以做的是将environment父节点添加到文件中的每个节点,然后执行小技巧(最后 2 个代码片段)。

假设您有一个配置,例如在appsettings.jsonor中appsettings.{environment}.json

{
  "Key1": "value1",
  "Secret1": "<set yourself>"
}
Run Code Online (Sandbox Code Playgroud)

然后你就有了秘密部分secrets.json

{
  "Secret1": "my secret value"
}
Run Code Online (Sandbox Code Playgroud)

您可以轻松获取并绑定整个部分:

IConfiguration configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddJsonFile($"appsettings.{environment}.json")
    .AddUserSecrets<Program>()
    .Build();
var myConfiguration = configuration.Get<MyConfiguration>();
Run Code Online (Sandbox Code Playgroud)

现在问题来了,我想在secrets.json. 我个人曾经对我需要的所有环境都有秘密,只需注释/取消注释我想要的内容,但是,这是手动工作。所以我会用environment名称作为前缀。

{
  "Development:Secret1": "my secret development value",
  "Staging:Secret1": "my secret staging value"
}
Run Code Online (Sandbox Code Playgroud)

您必须从实例加载特定于环境的配置IConfiguration并使用以下方法覆盖现有myConfiguration值:

configuration.GetSection(environment).Bind(myConfiguration);
\\ or
configurationRoot.Bind(environment, configuration);
Run Code Online (Sandbox Code Playgroud)

就是这样。

如果您使用 运行它environment="Development",您将已经"my secret development value"加载。如果您使用 运行它environment="Staging",您将已经"my secret staging value"加载。

额外细节

双点字符 ( :) 充当新部分,因此如果您编写

{
  "Development:Secret1": "my secret development value",
  "Staging:Secret1": "my secret staging value"
}
Run Code Online (Sandbox Code Playgroud)

它是一样的

{
  "Development":
  {
    "Secret1": "my secret development value"
  },
  "Staging":
  {
    "Secret1": "my secret staging value"
  }
}
Run Code Online (Sandbox Code Playgroud)

诀窍在于仅加载特定于环境的部分并将其绑定到实例myConfiguration

我必须提到的是,无论您使用什么环境,所有秘密实际上都加载到内存中。