【问题标题】:How to correctly store connection strings in environment variables for retrieval by production ASP.Net Core MVC applications如何在环境变量中正确存储连接字符串以供生产 ASP.Net Core MVC 应用程序检索
【发布时间】:2017-12-09 10:33:54
【问题描述】:

我正在开发一个 ASP.NET Core MVC 应用程序,但我的连接字符串有问题。

我的生产服务器上有一个 ASPNETCORE_ENVIRONMENT 变量设置为 Production,我的生产服务器是运行 IIS 的 Windows Server 2012R2。我还在生产服务器上安装了 DotNetCore.1.0.4_1.1.1-WindowsHosting.exe。

在开发过程中,我使用UserSecrets 来保存我的连接字符串。这工作正常。

对于生产,我希望我的连接字符串在生产服务器上的环境变量中,这就是我遇到问题的地方。我怀疑这可能是我构建环境变量的方式。

当我尝试访问生产中的数据库时,我收到一个错误,表明它无法解析连接字符串。

An exception occurred in the database while iterating the results of a query.

System.ArgumentException: Keyword not supported: '"server'.
at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary`2 
parsetable, String connectionString, Boolean buildChain, Dictionary`2 synonyms)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary`2 synonyms)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)

如果我将连接字符串放在appSettings.json 中,生产服务器就可以正常工作。

所以,这是我的 appSettings.json 文件的示例,显示了在生产中有效的连接字符串;

{
  "ConnectionStrings": {
     "TestDb": "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"
  },

    ...
    ...
    ...
  }
}

如果我将此appSettings.json 文件部署到生产环境,它可以正常工作。

在我的 ASP.Net Core 应用程序的 Startup.cs 文件中,我有以下内容;

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    if (env.IsDevelopment())
    {
        // For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709
        builder.AddUserSecrets<Startup>();
    }

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();

}

我的理解是最后列出的 builder.add... 具有优先级,所以在我的情况下,如果环境中存在连接字符串,它应该优先于 appsettings 中的任何内容。

所以在生产中,如果我使用下面的 appSettings.config 文件;

{
  "ConnectionStrings": {
     "TestDb": "Placeholder for connection string. Overridden by User Secrets in Development and Environment Variables in Production. "
  },

    ...
    ...
    ...
  }
}

如果我有一个用于连接字符串的环境变量,那么我在该appsettings.json 文件中拥有的ConnectionStrings:TestDb 的值并不重要。

下面列出的是我正在使用的环境变量;

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

但是,当我使用此设置时,我在尝试访问数据库时收到错误消息,指出它无法解析连接字符串。

我不得不假设问题是我在环境变量中指定连接字符串的方式,但是在网上搜索了一段时间后,我一直无法找到环境变量值应该是什么样子的示例喜欢。例如,我是否需要在整个字符串前后加上单引号?连接字符串的各个部分需要单引号还是双引号?

任何帮助,例如在环境变量中定义的正确连接字符串的示例,将不胜感激。

【问题讨论】:

  • 你没有一个 appSettings.Production.config 文件用于 prod 中的设置吗?
  • 对不起,现在我看到了。您的连接字符串中有引号,错误消息也告诉它。 '"server',乞讨时有"。当您在某处设置它时,您可能添加了"。即$env:ConnectionStrings:MyDb = """Server=;""",但正确的是$env:ConnectionStrings:MyDb = "Server=;",这也由您的环境变量输出确认
  • 我正在将连接字符串直接复制并粘贴到 Windows“新系统变量”对话框中,该对话框是系统属性控制面板的一部分(即控制面板 --> 所有控制面板项 --> 系统-->Advanced System Settings -->Environment Variables-->System Variables-->New... --> 然后我将变量名设置为 ASPNETCORE_TestDB 并将变量值设置为 "TestDb": "Server=TestServer;Database= TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true" 包括前导/尾随引号。这仍然会出现错误。
  • 我尝试了完全相同的方法,但没有任何前导和尾随引号,我仍然收到错误

标签: c# asp.net-core environment-variables asp.net-core-mvc


【解决方案1】:

在您的配置中,您有这一行:

.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

这告诉您的配置系统可能存在一个 JSON 文件,其中包含特定于环境的设置。因此,您只需要存在于生产盒中的名为 appSettings.Production.config 的文件,其中包含以下内容:

{
  "ConnectionStrings": {
     "TestDb": "Server=...;Catalog=...;Etc=..."
  }
}

此处的值将覆盖基本 JSON 设置文件中指定的任何内容。

【讨论】:

  • 是的,我明白这一点,但我要问的是环境变量,在我的设置中,它应该优先于其他任何东西,因为行... builder.AddEnvironmentVariables();是构建器链中的最后一个。我想使用环境变量来避免在生产中处理包含连接字符串的文件。
【解决方案2】:

如果不想存入appsettings,存入文件 C:\Windows\System32\inetsrv\config\applicationHost.config。它将能够工作。

【讨论】:

  • 感谢您的回复,但如果可能的话,我真的更喜欢使用环境变量,这样我就不必担心在生产系统上管理文件。这就是我发帖的原因。
【解决方案3】:

在您的连接变量中设置了错字/错误值。

在您粘贴的这个输出中可以看到:

Variable                    Value
ConnectionStrings:TestDb    "Server=TestServer;Database=TestDb;Persist Security Info=True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true"

这可能发生在通过设置变量时

$env:ConnectionStrings:MyDb = """Server=..."""

正确的方法是设置不带引号。

$env:ConnectionStrings:MyDb = "Server=..."

旧答案(对于可能搜索类似问题的其他用户)

连接字符串的约定是 SQLCONNSTR_MYSQLCONNSTR_SQLAZURECONNSTR_CUSTOMCONNSTR_,它们供 Azure Web 应用使用,但也适用于自托管、VM 或任何其他云提供商。

因此,如果您有一个名为 CUSTOMCONNSTR_TestDb 的环境变量,它将与在 appsettings.json 中定义它相同

{
    "connectionStrings": {
        "TestDb": "..."
    }
}

如果在.UseJsonFile(...) 之后调用AddEnvironmentVariables(),它也会覆盖其中的值。最后注册获胜。

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    // This one needs to be last
    .AddEnvironmentVariables();

您还可以使用其他变量来覆盖配置值。 iirc。 ASPNETCORE_ 是默认前缀(但您可以在 AddEnvironmentVariables("MY_") 中更改它)。

所以ASPNETCORE_MySettings 覆盖Configuration["MySettings"](或Configuration.Get("MySettings"))和ASPNETCORE_My__Settings(在Linux 上使用双下划线 表示级别层次结构,阅读: 用于获取配置的位置- Linux 不允许在变量名中使用冒号)覆盖 Configuration["My:Settings"]

相同
{
    "my": {
        "settings": "..."
    }
}

除非他们最近改变了这一点。

FWIW:据我记忆,环境变量/配置键名不区分大小写。

【讨论】:

  • Tseng - 所以你是说如果我的 appSettings.json 文件有一个工作连接字符串定义为“ConnectionStrings”:{“TestDb”:“Server=TestServer;Database=TestDb;Persist Security Info= True;User ID=TestUser;Password=testpassword;MultipleActiveResultSets=true" ...我将我的环境变量命名为“ASPNETCORE_TestDB”?还是应该命名为 SQLCONNSTR_TestDb" ?
  • 它不必在appsettings.json 中定义,但有助于测试在那里有开发连接字符串并通过环境变量覆盖它,即CUSTOMCONNSTR_TestDb)
  • 好的,我尝试将环境变量名称设置为 CUSTOMCONNSTR_TestDb 作为变量和我一直使用的相同连接字符串,但我仍然收到原始帖子开头列出的错误。错误消息包含字符串“System.ArgumentException: Keyword not supported: '"server'.",这让我认为我的实际连接字符串值的格式不正确,无法用作环境变量的值。
  • 好的,我的代码似乎根本没有检查环境变量 ASPNETCORE_TestDb。我得到的错误是因为我有 "ConnectionStrings": { "TestDb": "Placeholder for connection string. Overridden by User Secrets in Development and Environment Variables in Production." } 在我的生产 appSettings.json 文件中提醒任何查看文件的人都认为连接字符串应该来自环境变量。
  • 不是ASPNETCORE_TestDb,这会假设您的连接字符串在appsettings.json的root元素中,但它在连接字符串中,所以应该是@在 Windows 上为 987654346@ 或 ASPNETCORE_ConnectionStrings:TestDb,因为它在环境变量中支持 :。我发现的最后一件事是this change/announcement 关于它被更改为ASPNETCORE_,但是如果你不喜欢它可以删除前缀.AddEnvironmentVariables("")
猜你喜欢
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 2017-08-24
  • 2017-12-18
  • 2017-09-23
  • 2018-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多