Прочитать на английском

Поделиться через


Построители конфигураций для ASP.NET

Стивен Моллой и Рик Андерсон

Построитель конфигураций предоставляет современный и гибкий механизм для ASP.NET приложений для получения значений конфигурации из внешних источников.

Построители конфигураций:

  • Доступны в платформа .NET Framework версии 4.7.1 и более поздних версий.
  • Предоставьте гибкий механизм чтения значений конфигурации.
  • Решение некоторых основных потребностей приложений при переходе в контейнерную и облачную среду.
  • Можно использовать для повышения защиты данных конфигурации путем получения из источников, ранее недоступных (например, переменных Azure Key Vault и среды) в системе конфигурации .NET.

Построители конфигураций key/value

Распространенный сценарий, который может обрабатываться построителями конфигураций, — предоставить базовый механизм замены ключа и значения для разделов конфигурации, которые соответствуют шаблону ключа или значения. Концепция ConfigurationBuilders платформа .NET Framework не ограничивается определенными разделами конфигурации или шаблонами. Однако многие построители конфигураций в Microsoft.Configuration.ConfigurationBuilders (github, NuGet) работают в шаблоне key/value.

Параметры построителей конфигураций key/value

Следующие параметры применяются ко всем построителям конфигураций ключей и значений в Microsoft.Configuration.ConfigurationBuilders.

Режим

Построитель конфигураций использует внешний источник сведений о ключах и значении для заполнения выбранных элементов конфигурации key/value. В частности, разделы <appSettings/> <connectionStrings/> получают специальное лечение от построителей конфигураций. Построители работают в трех режимах:

  • Strict — режим по умолчанию. В этом режиме построитель конфигураций работает только в известных разделах конфигурации с ключом или значением. Strict режим перечисляет каждый ключ в разделе. Если соответствующий ключ найден во внешнем источнике:

    • Построители конфигураций заменяют значение в результирующем разделе конфигурации значением из внешнего источника.
  • Greedy — Этот режим тесно связан с режимом Strict . Вместо того чтобы ограничиваться ключами, которые уже существуют в исходной конфигурации:

    • Построитель конфигураций добавляет все пары "ключ-значение" из внешнего источника в результирующий раздел конфигурации.
  • Expand — работает с необработанным XML-файлом перед анализом объекта раздела конфигурации. Его можно рассматривать как расширение маркеров в строке. Любая часть необработанной XML-строки, которая соответствует шаблону ${token} , является кандидатом на расширение маркера. Если соответствующее значение не найдено во внешнем источнике, маркер не изменяется. Построители в этом режиме не ограничиваются <appSettings/> разделами и <connectionStrings/> разделами.

Следующая разметка из web.config включает EnvironmentConfigBuilder в Strict режиме:

<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 в редакторе среды:

Снимок экрана: редактор переменных среды с выделенными переменными ServiceID и ServiceKey.

Примечание. Для просмотра изменений в переменных среды может потребоваться выйти и перезапустить Visual Studio.

Обработка префикса

Префиксы ключей могут упростить параметры ключей, так как:

  • Конфигурация платформа .NET Framework сложна и вложена.
  • Внешние источники ключей и значений обычно являются основными и неструктурированными по природе. Например, переменные среды не вложены.

Используйте любой из следующих подходов для внедрения как <appSettings/> в конфигурацию, так и <connectionStrings/> в конфигурацию с помощью переменных среды:

  • EnvironmentConfigBuilder С помощью режима по умолчанию Strict и соответствующих имен ключей в файле конфигурации. Приведенный выше код и разметка принимают этот подход. Используя этот подход, вы не можете иметь одинаковые именованные ключи в обоих <appSettings/> и<connectionStrings/>.
  • Используйте два EnvironmentConfigBuilderрежима в Greedy режиме с отдельными префиксами и stripPrefix. С помощью этого подхода приложение может считывать <appSettings/> и <connectionStrings/> без необходимости обновлять файл конфигурации. В следующем разделе, stripPrefix, показано, как это сделать.
  • Используйте два EnvironmentConfigBuilderрежима в Greedy режиме с различными префиксами. При таком подходе не удается дублировать имена ключей, так как имена ключей должны отличаться префиксом. Например:
<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>

В приведенной выше разметке один и тот же источник неструктурированного ключа и значения можно использовать для заполнения конфигурации для двух разных разделов.

На следующем рисунке показаны <appSettings/> значения и ключи из <connectionStrings/> предыдущего файла конфигурации web.config в редакторе среды:

Снимок экрана: редактор переменных среды с выделенными переменными AppSetting_default, AppSetting_ServiceID и ConnStr_default переменными.

Следующий код считывает <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 AppSetting_ServiceID из переменных env
AppSetting_default значение AppSetting_default из env
ConnStr_default ConnStr_default val из env

stripPrefix

stripPrefix: boolean, по умолчанию 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 ключ находится как в файле<appSettings/>, default так и <connectionStrings/>.

На следующем рисунке показаны <appSettings/> значения и ключи из <connectionStrings/> предыдущего файла конфигурации web.config в редакторе среды:

Снимок экрана: редактор переменных среды с выделенными переменными AppSetting_default, AppSetting_ServiceID и ConnStr_default переменными.

Следующий код считывает <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 AppSetting_ServiceID из переменных env
default значение AppSetting_default из env
default ConnStr_default val из env

tokenPattern

tokenPattern: Строка, по умолчанию — @"\$\{(\w+)\}"

Поведение Expand построителей выполняет поиск необработанных XML-файлов для маркеров, которые выглядят следующим ${token}образом. Поиск выполняется с регулярным выражением @"\$\{(\w+)\}"по умолчанию. Набор символов, соответствующих \w более строгим, чем xml, и многие источники конфигурации позволяют. Используйте, если в имени токена требуется tokenPattern больше символов @"\$\{(\w+)\}" .

tokenPattern:Струна:

  • Позволяет разработчикам изменять регрессию, используемую для сопоставления маркеров.
  • Проверка не выполняется, чтобы убедиться, что она является хорошо сформированной, неопасной регрессией.
  • Он должен содержать группу отслеживания. Вся регрессия должна соответствовать всему токену. Первый захват должен быть именем маркера для поиска в источнике конфигурации.

Построители конфигураций в Microsoft.Configuration.ConfigurationBuilders

EnvironmentConfigBuilder

<add name="Environment"
    [mode|prefix|stripPrefix|tokenPattern] 
    type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder,
    Microsoft.Configuration.ConfigurationBuilders.Environment" />

EnvironmentConfigBuilder:

  • Самый простой из построителей конфигураций.
  • Считывает значения из среды.
  • Не имеет дополнительных параметров конфигурации.
  • Значение name атрибута является произвольным.

Примечание. В среде контейнера Windows переменные, заданные во время выполнения, внедряются только в среду процесса EntryPoint. Приложения, которые выполняются как услуга или процесс, отличный от EntryPoint, не собирают эти переменные, если они не внедряются через механизм в контейнере. Для контейнеров на основе IIS/ASP.NET текущая версия ServiceMonitor.exe обрабатывает эту версию только в DefaultAppPool. Другим вариантам контейнеров на основе Windows может потребоваться разработать собственный механизм внедрения для процессов, отличных от EntryPoint.

UserSecretsConfigBuilder

Предупреждение

Никогда не храните пароли, конфиденциальные строка подключения или другие конфиденциальные данные в исходном коде. Рабочие секреты не должны использоваться для разработки или тестирования.

<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 Core Secret Manager.

UserSecretsConfigBuilder можно использовать в платформа .NET Framework проектах, но необходимо указать файл секретов. Кроме того, можно определить UserSecretsId свойство в файле проекта и создать необработанный файл секретов в правильном расположении для чтения. Чтобы сохранить внешние зависимости вне проекта, секретный файл форматируется в формате XML. Форматирование XML — это подробные сведения о реализации, и формат не следует полагаться на них. Если вам нужно предоставить общий доступ к файлу secrets.json с проектами .NET Core, рассмотрите возможность использования SimpleJsonConfigBuilder. Формат SimpleJsonConfigBuilder .NET Core также должен рассматриваться как сведения о реализации, подлежащие изменению.

Атрибуты конфигурации для UserSecretsConfigBuilder:

  • userSecretsId — Это предпочтительный метод для идентификации XML-файла секретов. Он работает аналогично .NET Core, который использует UserSecretsId свойство проекта для хранения этого идентификатора. Строка должна быть уникальной, она не должна быть ИДЕНТИФИКАТОРом GUID. С помощью этого атрибута внешний вид в известном локальном расположении (%APPDATA%\Microsoft\UserSecrets\<UserSecrets Id>\secrets.xml) для файла секретов, UserSecretsConfigBuilder относящегося к этому идентификатору.
  • 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>

AzureKeyVaultConfigBuilder

<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 Key Vault.

vaultName требуется (имя хранилища или универсальный код ресурса (URI) в хранилище). Другие атрибуты позволяют управлять подключением к хранилищу, но необходимы только в том случае, если приложение не работает в среде, с Microsoft.Azure.Services.AppAuthenticationкоторой работает. Библиотека проверки подлинности служб Azure используется для автоматического сбора сведений о подключении из среды выполнения, если это возможно. Вы можете автоматически переопределить сведения о подключении, предоставив строка подключения.

  • vaultName — Обязательный, если uri он не указан. Указывает имя хранилища в подписке Azure, из которой следует считывать пары "ключ-значение".
  • uri — подключается к другим поставщикам Key Vault с указанным uri значением. Если это не указано, Azure (vaultName) является поставщиком хранилища.
  • version — Azure Key Vault предоставляет функцию управления версиями для секретов. Если version задано, построитель получает только секреты, соответствующие этой версии.
  • preloadSecretNames — По умолчанию этот построитель запрашивает все имена ключей в хранилище ключей при инициализации. Чтобы предотвратить чтение всех ключевых значений, задайте для этого атрибута значение false. Установка этого параметра для false чтения секретов по одному за раз. Чтение секретов по одному за раз может оказаться полезным, если хранилище разрешает доступ "Получить", но не "Список". Примечание. При использовании Greedy режима preloadSecretNames должно быть true (значение по умолчанию).)

KeyPerFileConfigBuilder

<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 — обязательный. Указывает путь для поиска значений. Секреты Docker для Windows хранятся в каталоге C:\ProgramData\Docker\secret по умолчанию.
  • ignorePrefix — Файлы, начинающиеся с этого префикса, исключаются. Значение по умолчанию — "ignore.".
  • keyDelimiter — Значение по умолчанию — null. Если задано, построитель конфигурации проходит по нескольким уровням каталога, создавая имена ключей с помощью этого разделителя. Если это значение равно null, построитель конфигураций смотрит только на верхний уровень каталога.
  • optional — Значение по умолчанию — false. Указывает, должен ли построитель конфигураций вызывать ошибки, если исходный каталог не существует.

SimpleJsonConfigBuilder

Предупреждение

Никогда не храните пароли, конфиденциальные строка подключения или другие конфиденциальные данные в исходном коде. Рабочие секреты не должны использоваться для разработки или тестирования.

<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 позволяет использовать ФАЙЛЫ JSON .NET Core в платформа .NET Framework. Этот построитель конфигураций предоставляет базовое сопоставление из источника неструктурированных ключей и значений в определенные области ключей и значений конфигурации платформа .NET Framework. Этот построитель конфигураций не предоставляет иерархические конфигурации. Резервный файл JSON похож на словарь, а не сложный иерархический объект. Можно использовать иерархический файл с несколькими уровнями. Этот поставщик flattenглубины добавляет имя свойства на каждом уровне, используя : его в качестве разделителя.

Сведения о атрибуте:

  • jsonFile — обязательный. Указывает JSON-файл для чтения из. Символ ~ можно использовать в начале для ссылки на корневой каталог приложения.

  • optional — Логическое значение, значение по умолчанию — true. Предотвращает создание исключений, если не удается найти JSON-файл.

  • jsonMode - [Flat|Sectional]. Значение по умолчанию — Flat. В противном случае jsonMode FlatJSON-файл является одним неструктурированным источником ключа и значения. Они EnvironmentConfigBuilder AzureKeyVaultConfigBuilder также являются источниками с одним неструктурированным ключом и значением. При настройке в Sectional режимеSimpleJsonConfigBuilder:

    • JSON-файл концептуально делится только на верхнем уровне на несколько словарей.
    • Каждый из словарей применяется только к разделу конфигурации, который соответствует имени свойства верхнего уровня, присоединенному к ним. Например:
    {
        "appSettings" : {
            "setting1" : "value1",
            "setting2" : "value2",
            "complex" : {
                "setting1" : "complex:value1",
                "setting2" : "complex:value2",
            }
        }
    }

Порядок построителей конфигураций

См. раздел "Порядок выполнения ConfigurationBuilders" в репозитории aspnet/MicrosoftConfigurationBuilders GitHub.

Реализация построителя конфигураций пользовательского ключа и значения

Если построители конфигураций не соответствуют вашим потребностям, можно написать пользовательский. Базовый KeyValueConfigBuilder класс обрабатывает режимы подстановки и большинство проблем префикса. Для реализации проекта требуется только следующее:

  • Наследуется от базового класса и реализует базовый источник пар "ключ-значение" с помощью GetValue и GetAllValues:
  • Добавьте в проект Microsoft.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 класс обеспечивает большую часть работы и согласованного поведения в построителях конфигураций ключей и значений.

Дополнительные ресурсы