ASP.NET 的配置生成器
配置生成器为 ASP.NET 应用提供新式和敏捷的机制,用于从外部源获取配置值。
配置生成器:
- 可在 .NET Framework 4.7.1 及更高版本中使用。
- 提供用于读取配置值的灵活机制。
- 在应用进入容器和云重点环境时,解决应用的某些基本需求。
- 可以通过从以前不可用的源(例如 Azure 密钥库 和环境变量)中绘制来改进配置数据的保护。
配置生成器可以处理的常见方案是为遵循键/值模式的配置节提供基本键/值替换机制。 ConfigurationBuilders 的 .NET Framework 概念不限于特定的配置部分或模式。 但是,(github,NuGet)中的Microsoft.Configuration.ConfigurationBuilders
许多配置生成器在键/值模式中工作。
以下设置适用于所有键/值配置生成器。Microsoft.Configuration.ConfigurationBuilders
配置生成器使用键/值信息的外部源来填充配置系统的所选键/值元素。 具体而言, <appSettings/>
这些和 <connectionStrings/>
部分从配置生成器处获得特殊处理。 构建者以三种模式工作:
Strict
- 默认模式。 在此模式下,配置生成器仅对以已知键/以值为中心的配置部分进行操作。Strict
模式枚举节中的每个键。 如果在外部源中找到匹配的键:- 配置生成器将生成的配置部分中的值替换为外部源中的值。
Greedy
- 此模式与模式密切相关Strict
。 不限于原始配置中已存在的密钥:- 配置生成器会将外部源中的所有键/值对添加到生成的配置部分。
Expand
- 在分析到配置节对象之前,先对原始 XML 进行操作。 可以将其视为字符串中标记的扩展。 与模式${token}
匹配的原始 XML 字符串的任何部分都是令牌扩展的候选项。 如果在外部源中找不到相应的值,则不会更改令牌。 此模式下的生成器不限于<appSettings/>
这些和<connectionStrings/>
部分。
Web.config 中的以下标记在Strict
模式下启用 EnvironmentConfigBuilder:
<configuration>
<configSections>
<section name="configBuilders"
type="System.Configuration.ConfigurationBuildersSection,
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false" requirePermission="false" />
</configSections>
<configBuilders>
<builders>
<add name="MyEnvironment"
type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Environment,
Version=1.0.0.0, Culture=neutral" />
</builders>
</configBuilders>
<appSettings configBuilders="MyEnvironment">
<add key="ServiceID" value="ServiceID value from web.config" />
<add key="ServiceKey" value="ServiceKey value from web.config" />
</appSettings>
<connectionStrings configBuilders="MyEnvironment">
<add name="default" connectionString="Data Source=web.config/mydb.db" />
</connectionStrings>
以下代码读取<appSettings/>
<connectionStrings/>
前面 web.config 文件中所示的内容:
using System;
using System.Configuration;
using System.Web.UI;
namespace MyConfigBuilders
{
public partial class About : Page
{
public string ServiceID { get; set; }
public string ServiceKey { get; set; }
public string ConString { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
ServiceID = ConfigurationManager.AppSettings["ServiceID"];
ServiceKey = ConfigurationManager.AppSettings["ServiceKey"];
ConString = ConfigurationManager.ConnectionStrings["default"]
?.ConnectionString;
}
}
}
前面的代码将属性值设置为:
- 如果未在 环境变量中设置密钥,则 web.config 文件中的值。
- 环境变量的值(如果已设置)。
例如, ServiceID
将包含:
- 如果未设置环境变量
ServiceID
,则为“web.config 中的 ServiceID 值”。 - 环境变量的值
ServiceID
(如果已设置)。
下图显示了 <appSettings/>
环境编辑器中上 一个 web.config 文件中设置的键/值:
注意:可能需要退出并重启 Visual Studio 才能查看环境变量中的更改。
键前缀可以简化设置键,因为:
- .NET Framework 配置复杂且嵌套。
- 外部键/值源通常是基本和平面的。 例如,环境变量不是嵌套的。
使用以下任一方法通过 <appSettings/>
环境变量注入和 <connectionStrings/>
注入配置:
- 在
EnvironmentConfigBuilder
默认Strict
模式下,配置文件中具有相应的密钥名称。 前面的代码和标记采用此方法。 使用此方法时,不能在两者<appSettings/>
中<connectionStrings/>
具有相同命名的键。 - 在模式中使用
Greedy
具有不同前缀的两EnvironmentConfigBuilder
个 s 和stripPrefix
。 使用此方法,应用可以读取<appSettings/>
和<connectionStrings/>
无需更新配置文件。 下一部分 stripPrefix 演示如何执行此操作。 - 在模式中使用
Greedy
两EnvironmentConfigBuilder
个具有不同前缀的 s。 使用此方法时,不能有重复的键名称,因为密钥名称必须因前缀而异。 例如:
<configuration>
<configSections>
<section name="configBuilders"
type="System.Configuration.ConfigurationBuildersSection,
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false" requirePermission="false" />
</configSections>
<configBuilders>
<builders>
<add name="AS_Environment" mode="Greedy" prefix="AppSetting_"
type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Environment" />
<add name="CS_Environment" mode="Greedy" prefix="ConnStr_"
type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Environment" />
</builders>
</configBuilders>
<appSettings configBuilders="AS_Environment">
<add key="AppSetting_ServiceID" value="ServiceID value from web.config" />
<add key="AppSetting_default" value="AppSetting_default value from web.config" />
</appSettings>
<connectionStrings configBuilders="CS_Environment">
<add name="ConnStr_default" connectionString="Data Source=web.config/mydb.db" />
</connectionStrings>
使用前面的标记,可以使用同一平面键/值源来填充两个不同的部分的配置。
下图显示了环境编辑器中上一个 web.config 文件中设置的<appSettings/>
<connectionStrings/>
键/值:
以下代码读取<appSettings/>
<connectionStrings/>
前面 web.config 文件中包含的键/值:
public partial class Contact : Page
{
public string ServiceID { get; set; }
public string AppSetting_default { get; set; }
public string ConString { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
ServiceID = ConfigurationManager.AppSettings["AppSetting_ServiceID"];
AppSetting_default = ConfigurationManager.AppSettings["AppSetting_default"];
ConString = ConfigurationManager.ConnectionStrings["ConnStr_default"]
?.ConnectionString;
}
}
前面的代码将属性值设置为:
- 如果未在 环境变量中设置密钥,则 web.config 文件中的值。
- 环境变量的值(如果已设置)。
例如,使用以前的 web.config 文件、上一环境编辑器映像中的键/值和上一个代码,将设置以下值:
密钥 | 值 |
---|---|
AppSetting_ServiceID | env 变量AppSetting_ServiceID |
AppSetting_default | 来自 env 的AppSetting_default值 |
ConnStr_default | 从 env ConnStr_default val |
stripPrefix
:布尔值,默认值为 false
.
前面的 XML 标记将应用设置与连接字符串分开,但要求 web.config 文件中的所有键都使用指定的前缀。 例如,必须将前缀 AppSetting
添加到 ServiceID
密钥(“AppSetting_ServiceID”)。 使用 stripPrefix
时,该前缀不会在 web.config 文件中使用。 配置生成器源中需要前缀(例如,在环境中)。我们预计大多数开发人员都将使用 stripPrefix
。
应用程序通常去除前缀。 以下 web.config 将去除前缀:
<configuration>
<configSections>
<section name="configBuilders"
type="System.Configuration.ConfigurationBuildersSection,
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false" requirePermission="false" />
</configSections>
<configBuilders>
<builders>
<add name="AS_Environment" mode="Greedy" prefix="AppSetting_"
stripPrefix="true"
type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Environment,
Version=1.0.0.0, Culture=neutral" />
<add name="CS_Environment" mode="Greedy" prefix="ConnStr_"
stripPrefix="true"
type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Environment,
Version=1.0.0.0, Culture=neutral" />
</builders>
</configBuilders>
<appSettings configBuilders="AS_Environment">
<add key="ServiceID" value="ServiceID value from web.config" />
<add key="default" value="AppSetting_default value from web.config" />
</appSettings>
<connectionStrings configBuilders="CS_Environment">
<add name="default" connectionString="Data Source=web.config/mydb.db" />
</connectionStrings>
在前面的 web.config 文件中, default
密钥同时位于 <appSettings/>
和 <connectionStrings/>
中。
下图显示了环境编辑器中上一个 web.config 文件中设置的<appSettings/>
<connectionStrings/>
键/值:
以下代码读取<appSettings/>
<connectionStrings/>
前面 web.config 文件中包含的键/值:
public partial class About2 : Page
{
public string ServiceID { get; set; }
public string AppSetting_default { get; set; }
public string ConString { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
ServiceID = ConfigurationManager.AppSettings["ServiceID"];
AppSetting_default = ConfigurationManager.AppSettings["default"];
ConString = ConfigurationManager.ConnectionStrings["default"]
?.ConnectionString;
}
}
前面的代码将属性值设置为:
- 如果未在 环境变量中设置密钥,则 web.config 文件中的值。
- 环境变量的值(如果已设置)。
例如,使用以前的 web.config 文件、上一环境编辑器映像中的键/值和上一个代码,将设置以下值:
密钥 | 值 |
---|---|
ServiceID | env 变量AppSetting_ServiceID |
default | 来自 env 的AppSetting_default值 |
default | 从 env ConnStr_default val |
tokenPattern
:字符串,默认值为 @"\$\{(\w+)\}"
Expand
生成器的行为在原始 XML 中搜索类似于${token}
的标记。 使用默认正则表达式 @"\$\{(\w+)\}"
完成搜索。 匹配 \w
的字符集比 XML 更严格,并且许多配置源都允许。 在令牌名称中需要的字符数多@"\$\{(\w+)\}"
时使用tokenPattern
。
tokenPattern
:字符串:
- 允许开发人员更改用于令牌匹配的正则表达式。
- 没有验证,以确保它是一个格式正确的非危险正则表达式。
- 它必须包含捕获组。 整个正则表达式必须与整个令牌匹配。 第一个捕获必须是要在配置源中查找的令牌名称。
<add name="Environment"
[mode|prefix|stripPrefix|tokenPattern]
type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Environment" />
- 最简单的配置生成器。
- 从环境中读取值。
- 没有任何其他配置选项。
- 属性值
name
是任意的。
注意: 在 Windows 容器环境中,运行时设置的变量仅注入到 EntryPoint 进程环境中。 作为服务或非 EntryPoint 进程运行的应用不会选取这些变量,除非通过容器中的机制注入这些变量。 对于基于 IIS/ASP.NET 的容器,当前版本的 ServiceMonitor.exe 仅在 DefaultAppPool 中处理此问题。 其他基于 Windows 的容器变体可能需要为非 EntryPoint 进程开发自己的注入机制。
警告
切勿在源代码中存储密码、敏感连接字符串或其他敏感数据。 不应将生产机密用于开发或测试。
<add name="UserSecrets"
[mode|prefix|stripPrefix|tokenPattern]
(userSecretsId="{secret string, typically a GUID}" | userSecretsFile="~\secrets.file")
[optional="true"]
type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.UserSecrets" />
在前面的 XML 中, userSecretsFile
路径可以使用 ~/
或 ~\
。 例如,路径可以编写为 userSecretsFile="~/secrets.file
。 有关详细信息, 请参阅 ConfigurationBuilders Utils 类。
此配置生成器提供的功能类似于 ASP.NET 核心机密管理器。
UserSecretsConfigBuilder 可用于 .NET Framework 项目,但必须指定机密文件。 或者,可以在项目文件中定义 UserSecretsId
属性,并在正确的位置创建原始机密文件进行读取。 若要使外部依赖项远离项目,机密文件的格式为 XML。 XML 格式是实现详细信息,不应依赖该格式。 如果需要与 .NET Core 项目共享 secrets.json 文件,请考虑使用 SimpleJsonConfigBuilder。 SimpleJsonConfigBuilder
还应将 .NET Core 的格式视为可能更改的实现详细信息。
的配置属性:UserSecretsConfigBuilder
userSecretsId
- 这是用于标识 XML 机密文件的首选方法。 它的工作方式类似于 .NET Core,它使用UserSecretsId
项目属性来存储此标识符。 字符串必须是唯一的,它不需要是 GUID。 使用此属性,查找UserSecretsConfigBuilder
属于此标识符的机密文件的已知本地位置(%APPDATA%\Microsoft\UserSecrets\<UserSecrets Id>\secrets.xml
)。userSecretsFile
- 指定包含机密的文件的可选属性。~
该字符可用于开始引用应用程序根目录。 此属性或userSecretsId
属性是必需的。 如果同时指定了两者,userSecretsFile
则优先。optional
:布尔值,默认值true
- 如果找不到机密文件,则阻止异常。- 属性值
name
是任意的。
机密文件的格式如下:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<secrets ver="1.0">
<secret name="secret key name" value="secret value" />
</secrets>
</root>
<add name="AzureKeyVault"
[mode|prefix|stripPrefix|tokenPattern]
(vaultName="MyVaultName" |
uri="https:/MyVaultName.vault.azure.net")
[version="secrets version"]
[preloadSecretNames="true"]
type="Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Azure" />
AzureKeyVaultConfigBuilder 读取存储在 Azure 密钥库中的值。
vaultName
是必需的(保管库的名称或保管库的 URI)。 其他属性允许控制要连接到哪个保管库,但仅在应用程序未在使用 Microsoft.Azure.Services.AppAuthentication
的环境中运行时才是必需的。 Azure 服务身份验证库可用于尽可能自动从执行环境中选取连接信息。 可以通过提供连接字符串来替代自动选取连接信息。
vaultName
- 如果未uri
提供,则为必需。 指定要从中读取密钥/值对的 Azure 订阅中的保管库的名称。uri
- 连接到具有指定uri
值的其他密钥库提供程序。 如果未指定,Azure (vaultName
) 是保管库提供程序。version
- Azure 密钥库为机密提供版本控制功能。 如果version
已指定,则生成器仅检索与此版本匹配的机密。preloadSecretNames
- 默认情况下,此生成器在初始化密钥保管库时查询 密钥保管库中的所有 密钥名称。 若要防止读取所有键值,请将此属性设置为false
。 将此设置设置为false
一次读取机密。 如果保管库允许“获取”访问,但不允许“列出”访问,则一次读取机密非常有用。 注意: 使用Greedy
模式时,preloadSecretNames
必须是true
(默认值)。
<add name="KeyPerFile"
[mode|prefix|stripPrefix|tokenPattern]
(directoryPath="PathToSourceDirectory")
[ignorePrefix="ignore."]
[keyDelimiter=":"]
[optional="false"]
type="Microsoft.Configuration.ConfigurationBuilders.KeyPerFileConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.KeyPerFile" />
KeyPerFileConfigBuilder 是一个基本配置生成器,它使用目录的文件作为值的源。 文件的名称是键,内容是值。 在协调的容器环境中运行时,此配置生成器非常有用。 Docker Swarm 和 Kubernetes 等系统以按文件密钥的方式提供给 secrets
其协调的 Windows 容器。
属性详细信息:
directoryPath
- 必需。 指定要查找值的路径。 默认情况下,适用于 Windows 的 Docker 机密存储在 C:\ProgramData\Docker\secrets 目录中。ignorePrefix
- 排除以此前缀开头的文件。 默认值为“忽略”。keyDelimiter
- 默认值为null
. 如果指定,配置生成器将遍历目录的多个级别,并使用此分隔符构建密钥名称。 如果值为此值null
,则配置生成器仅查看目录的顶层。optional
- 默认值为false
. 指定如果源目录不存在,配置生成器是否应导致错误。
警告
切勿在源代码中存储密码、敏感连接字符串或其他敏感数据。 不应将生产机密用于开发或测试。
<add name="SimpleJson"
[mode|prefix|stripPrefix|tokenPattern]
jsonFile="~\config.json"
[optional="true"]
[jsonMode="(Flat|Sectional)"]
type="Microsoft.Configuration.ConfigurationBuilders.SimpleJsonConfigBuilder,
Microsoft.Configuration.ConfigurationBuilders.Json" />
.NET Core 项目经常使用 JSON 文件进行配置。 SimpleJsonConfigBuilder 生成器允许在 .NET Framework 中使用 .NET Core JSON 文件。 此配置生成器提供从平面键/值源到 .NET Framework 配置的特定键/值区域的基本映射。 此配置生成器不提供分层配置。 JSON 支持文件类似于字典,而不是复杂的分层对象。 可以使用多层分层文件。 此提供程序 flatten
通过在每个级别追加属性名称(用作 :
分隔符)来深度。
属性详细信息:
jsonFile
- 必需。 指定要从中读取的 JSON 文件。~
该字符可用于在开始处引用应用根。optional
- 布尔值,默认值为true
. 如果找不到 JSON 文件,则防止引发异常。jsonMode
-[Flat|Sectional]
。Flat
是默认值。 如果jsonMode
为Flat
,JSON 文件是单个平面键/值源。EnvironmentConfigBuilder
并且AzureKeyVaultConfigBuilder
也是单个平面键/值源。SimpleJsonConfigBuilder
在Sectional
模式下配置时:- JSON 文件在概念上只分为多个字典。
- 每个字典仅应用于与附加到它们的顶级属性名称匹配的配置节。 例如:
{
"appSettings" : {
"setting1" : "value1",
"setting2" : "value2",
"complex" : {
"setting1" : "complex:value1",
"setting2" : "complex:value2",
}
}
}
请参阅 aspnet/MicrosoftConfigurationBuilders GitHub 存储库中的 ConfigurationBuilders 执行顺序。
如果配置生成器不满足你的需求,则可以编写自定义生成器。 KeyValueConfigBuilder
基类处理替换模式和大多数前缀问题。 实现项目只需要:
- 继承自基类,并通过
GetValue
以下项GetAllValues
实现键/值对的基本源: - 将 Microsoft.Configuration.ConfigurationBuilders.Base 添加到项目。
using Microsoft.Configuration.ConfigurationBuilders;
using System.Collections.Generic;
public class MyCustomConfigBuilder : KeyValueConfigBuilder
{
public override string GetValue(string key)
{
// Key lookup should be case-insensitive, because most key/value collections in
// .NET Framework config sections are case-insensitive.
return "Value for given key, or null.";
}
public override ICollection<KeyValuePair<string, string>> GetAllValues(string prefix)
{
// Populate the return collection.
return new Dictionary<string, string>() { { "one", "1" }, { "two", "2" } };
}
}
基 KeyValueConfigBuilder
类提供键/值配置生成器的大部分工作和一致行为。