Ler em inglês

Compartilhar via


Construtores de configuração para ASP.NET

Por Stephen Molloy e Rick Anderson

Os criadores de configuração fornecem um mecanismo moderno e ágil para que ASP.NET aplicativos obtenham valores de configuração de fontes externas.

Construtores de configuração:

  • Estão disponíveis no .NET Framework 4.7.1 e posterior.
  • Forneça um mecanismo flexível para ler valores de configuração.
  • Atenda a algumas das necessidades básicas dos aplicativos à medida que eles se movem para um ambiente focado em contêiner e nuvem.
  • Pode ser usado para melhorar a proteção de dados de configuração extraindo de fontes anteriormente indisponíveis (por exemplo, Azure Key Vault e variáveis de ambiente) no sistema de configuração do .NET.

Construtores de configuração de chave/valor

Um cenário comum que pode ser tratado por construtores de configuração é fornecer um mecanismo básico de substituição de chave/valor para seções de configuração que seguem um padrão de chave/valor. O conceito do .NET Framework de ConfigurationBuilders não se limita a seções ou padrões de configuração específicos. No entanto, muitos dos construtores de configuração em Microsoft.Configuration.ConfigurationBuilders (github, NuGet) funcionam dentro do padrão de chave/valor.

Configurações dos construtores de configuração de chave/valor

As configurações a seguir se aplicam a todos os construtores de configuração de chave/valor no Microsoft.Configuration.ConfigurationBuilders.

Mode

Os construtores de configuração usam uma fonte externa de informações de chave/valor para preencher os elementos de chave/valor selecionados do sistema de configuração. Especificamente, as <appSettings/> seções e <connectionStrings/> recebem tratamento especial dos construtores de configuração. Os construtores funcionam em três modos:

  • Strict - O modo padrão. Nesse modo, o construtor de configuração opera apenas em seções de configuração centradas em chave/valor conhecidas. Strict mode enumera cada chave na seção. Se uma chave correspondente for encontrada na fonte externa:

    • Os construtores de configuração substituem o valor na seção de configuração resultante pelo valor da fonte externa.
  • Greedy - Este modo está intimamente relacionado ao Strict modo. Em vez de se limitar a chaves que já existem na configuração original:

    • Os construtores de configuração adicionam todos os pares de chave/valor da fonte externa na seção de configuração resultante.
  • Expand - Opera no XML bruto antes de ser analisado em um objeto de seção de configuração. Pode ser pensado como uma expansão de tokens em uma string. Qualquer parte da cadeia de caracteres XML bruta que corresponda ao padrão ${token} é candidata à expansão do token. Se nenhum valor correspondente for encontrado na fonte externa, o token não será alterado. Os construtores neste modo não estão limitados às <appSettings/> seções e <connectionStrings/> .

A seguinte marcação de web.config habilita o EnvironmentConfigBuilder no Strict modo:

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

O código a seguir lê o <appSettings/> e <connectionStrings/> mostrado no arquivo web.config anterior:

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

O código anterior definirá os valores de propriedade como:

  • Os valores no arquivo web.config se as chaves não estiverem definidas em variáveis de ambiente.
  • Os valores da variável de ambiente, se definidos.

Por exemplo, ServiceID conterá:

  • "ServiceID value from web.config", se a variável ServiceID de ambiente não estiver definida.
  • O valor da variável de ServiceID ambiente, se definido.

A imagem a seguir mostra as <appSettings/> chaves/valores do arquivo web.config anterior definido no editor de ambiente:

A captura de tela mostra o editor de Variáveis Ambientais com as variáveis ServiceID e ServiceKey realçadas.

Observação: talvez seja necessário sair e reiniciar o Visual Studio para ver as alterações nas variáveis de ambiente.

Tratamento de prefixo

Os prefixos de chave podem simplificar a configuração de chaves porque:

  • A configuração do .NET Framework é complexa e aninhada.
  • As fontes externas de chave/valor são geralmente básicas e planas por natureza. Por exemplo, as variáveis de ambiente não são aninhadas.

Use qualquer uma das seguintes abordagens para injetar e <appSettings/> <connectionStrings/> na configuração por meio de variáveis de ambiente:

  • Com o EnvironmentConfigBuilder no modo padrão Strict e os nomes de chave apropriados no arquivo de configuração. O código e a marcação anteriores usam essa abordagem. Usando essa abordagem, você não pode ter chaves com nomes idênticos em ambos e <appSettings/> <connectionStrings/>.
  • Use dois EnvironmentConfigBuilders no Greedy modo com prefixos distintos e stripPrefix. Com essa abordagem, o aplicativo pode ler <appSettings/> e <connectionStrings/> sem precisar atualizar o arquivo de configuração. A próxima seção, stripPrefix, mostra como fazer isso.
  • Use dois EnvironmentConfigBuilders no Greedy modo com prefixos distintos. Com essa abordagem, você não pode ter nomes de chave duplicados, pois os nomes de chave devem ser diferentes por prefixo. Por exemplo:
<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>

Com a marcação anterior, a mesma fonte de chave/valor simples pode ser usada para preencher a configuração de duas seções diferentes.

A imagem a seguir mostra as <appSettings/> chaves/valores e <connectionStrings/> do arquivo web.config anterior definido no editor de ambiente:

A captura de tela mostra o editor de variáveis ambientais com as variáveis AppSetting_default, AppSetting_ServiceID e ConnStr_default realçadas.

O código a seguir lê as <appSettings/> chaves/valores e <connectionStrings/> contidos no arquivo web.config anterior:

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

O código anterior definirá os valores de propriedade como:

  • Os valores no arquivo web.config se as chaves não estiverem definidas em variáveis de ambiente.
  • Os valores da variável de ambiente, se definidos.

Por exemplo, usando o arquivo web.config anterior, as chaves/valores na imagem anterior do editor de ambiente e o código anterior, os seguintes valores são definidos:

Chave Valor
AppSetting_ServiceID AppSetting_ServiceID de variáveis env
AppSetting_default AppSetting_default valor do ambiente
ConnStr_default ConnStr_default val de env

stripPrefixo

stripPrefix: booleano, o padrão é false.

A marcação XML anterior separa as configurações do aplicativo das cadeias de conexão, mas requer que todas as chaves no arquivo web.config usem o prefixo especificado. Por exemplo, o prefixo AppSetting ServiceID deve ser adicionado à chave ("AppSetting_ServiceID"). Com stripPrefix, o prefixo não é usado no arquivo web.config . O prefixo é necessário na origem do construtor de configuração (por exemplo, no ambiente). Prevemos que a maioria dos desenvolvedores usará stripPrefixo .

Os aplicativos normalmente removem o prefixo. O web.config a seguir remove o prefixo:

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

No arquivo web.config anterior, a default chave está no <appSettings/> arquivo e <connectionStrings/>.

A imagem a seguir mostra as <appSettings/> chaves/valores e <connectionStrings/> do arquivo web.config anterior definido no editor de ambiente:

A captura de tela mostra o editor de variáveis ambientais com as variáveis AppSetting_default, AppSetting_ServiceID e ConnStr_default realçadas.

O código a seguir lê as <appSettings/> chaves/valores e <connectionStrings/> contidos no arquivo web.config anterior:

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

O código anterior definirá os valores de propriedade como:

  • Os valores no arquivo web.config se as chaves não estiverem definidas em variáveis de ambiente.
  • Os valores da variável de ambiente, se definidos.

Por exemplo, usando o arquivo web.config anterior, as chaves/valores na imagem anterior do editor de ambiente e o código anterior, os seguintes valores são definidos:

Chave Valor
ServiceID AppSetting_ServiceID de variáveis env
padrão AppSetting_default valor do ambiente
padrão ConnStr_default val de env

tokenPadrão

tokenPattern: String, o padrão é @"\$\{(\w+)\}"

O Expand comportamento dos construtores pesquisa o XML bruto em busca de tokens que se pareçam com ${token}. A pesquisa é feita com a expressão @"\$\{(\w+)\}"regular padrão . O conjunto de caracteres que corresponde \w é mais rigoroso do que o XML e muitas fontes de configuração permitem. Use tokenPattern quando mais caracteres do que @"\$\{(\w+)\}" o necessário no nome do token.

tokenPattern:Corda:

  • Permite que os desenvolvedores alterem o regex usado para correspondência de token.
  • Nenhuma validação é feita para garantir que seja um regex bem formado e não perigoso.
  • Ele deve conter um grupo de captura. Todo o regex deve corresponder ao token inteiro. A primeira captura deve ser o nome do token a ser pesquisado na fonte de configuração.

Construtores de configuração em Microsoft.Configuration.ConfigurationBuilders

Construtor de configuração de ambiente

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

O EnvironmentConfigBuilder:

  • É o mais simples dos construtores de configuração.
  • Lê valores do ambiente.
  • Não tem nenhuma opção de configuração adicional.
  • O name valor do atributo é arbitrário.

Nota: Em um ambiente de contêiner do Windows, as variáveis definidas no tempo de execução são injetadas apenas no ambiente de processo EntryPoint. Os aplicativos executados como um serviço ou um processo que não é do EntryPoint não selecionam essas variáveis, a menos que sejam injetadas por meio de um mecanismo no contêiner. Para contêineres baseados em ASP.NET do IIS/, a versão atual do ServiceMonitor.exe lida com isso somente no DefaultAppPool. Outras variantes de contêiner baseadas em Windows podem precisar desenvolver seu próprio mecanismo de injeção para processos que não são do EntryPoint.

UserSecretsConfigBuilder

Aviso

Nunca armazene senhas, cadeias de conexão confidenciais ou outros dados confidenciais no código-fonte. Os segredos de produção não devem ser usados para desenvolvimento ou teste.

<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" />

No XML anterior, o userSecretsFile caminho pode usar use ~/ ou ~\. Por exemplo, o caminho pode ser escrito como userSecretsFile="~/secrets.file. Consulte a classe ConfigurationBuilders Utils para obter mais informações.

Esse construtor de configuração fornece um recurso semelhante ao ASP.NET Core Secret Manager.

O UserSecretsConfigBuilder pode ser usado em projetos do .NET Framework, mas um arquivo de segredos deve ser especificado. Como alternativa, você pode definir a UserSecretsId propriedade no arquivo de projeto e criar o arquivo de segredos brutos no local correto para leitura. Para manter as dependências externas fora do seu projeto, o arquivo secreto é formatado em XML. A formatação XML é um detalhe de implementação e o formato não deve ser confiável. Se você precisar compartilhar um arquivo secrets.json com projetos do .NET Core, considere usar o SimpleJsonConfigBuilder. O SimpleJsonConfigBuilder formato do .NET Core também deve ser considerado um detalhe de implementação sujeito a alterações.

Atributos de configuração para UserSecretsConfigBuilder:

  • userSecretsId - Este é o método preferencial para identificar um arquivo de segredos XML. Ele funciona de forma semelhante ao .NET Core, que usa uma propriedade de UserSecretsId projeto para armazenar esse identificador. A cadeia de caracteres deve ser exclusiva, não precisa ser um GUID. Com esse atributo, procuramos UserSecretsConfigBuilder em um local conhecido (%APPDATA%\Microsoft\UserSecrets\<UserSecrets Id>\secrets.xml) um arquivo de segredos pertencente a esse identificador.
  • userSecretsFile - Um atributo opcional que especifica o arquivo que contém os segredos. O ~ caractere pode ser usado no início para fazer referência à raiz do aplicativo. Esse atributo ou o userSecretsId atributo é necessário. Se ambos forem especificados, userSecretsFile terá precedência.
  • optional: booleano, valor true padrão - Impede uma exceção se o arquivo de segredos não puder ser encontrado.
  • O name valor do atributo é arbitrário.

O arquivo de segredos tem o seguinte formato:

<?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" />

O AzureKeyVaultConfigBuilder lê valores armazenados no Azure Key Vault.

vaultName é necessário (o nome do vault ou um URI para o vault). Os outros atributos permitem o controle sobre a qual vault se conectar, mas só são necessários se o aplicativo não estiver sendo executado em um ambiente que funcione com Microsoft.Azure.Services.AppAuthenticationo . A biblioteca de Autenticação de Serviços do Azure é usada para coletar automaticamente informações de conexão do ambiente de execução, se possível. Você pode substituir automaticamente a coleta de informações de conexão fornecendo uma cadeia de conexão.

  • vaultName - Obrigatório se uri não for fornecido. Especifica o nome do cofre em sua assinatura do Azure a partir do qual ler pares chave/valor.
  • uri - Conecta-se a outros provedores do Key Vault com o valor especificado uri . Se não for especificado, Azure (vaultName) será o provedor do cofre.
  • version - O Azure Key Vault fornece um recurso de controle de versão para segredos. Se version for especificado, o construtor recuperará apenas os segredos correspondentes a essa versão.
  • preloadSecretNames- Por padrão, esse construtor consulta todos os nomes de chave no cofre de chaves quando ele é inicializado. Para impedir a leitura de todos os valores de chave, defina esse atributo como false. Definir isso para false ler os segredos um de cada vez. Ler segredos um de cada vez pode ser útil se o cofre permitir acesso "Obter", mas não acesso "Lista". Nota: Ao usar Greedy o modo, preloadSecretNames deve ser true (o padrão).

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 é um construtor de configuração básica que usa os arquivos de um diretório como fonte de valores. O nome de um arquivo é a chave e o conteúdo é o valor. Esse construtor de configuração pode ser útil ao ser executado em um ambiente de contêiner orquestrado. Sistemas como o Docker Swarm e o Kubernetes fornecem secrets aos contêineres do Windows orquestrados dessa maneira de chave por arquivo.

Detalhes do atributo:

  • directoryPath - Obrigatório. Especifica um caminho para procurar valores. Os segredos do Docker para Windows são armazenados no diretório C:\ProgramData\Docker\secrets por padrão.
  • ignorePrefix - Os arquivos que começam com esse prefixo são excluídos. O padrão é "ignorar".
  • keyDelimiter - O valor padrão é null. Se especificado, o construtor de configuração percorre vários níveis do diretório, criando nomes de chave com esse delimitador. Se esse valor for null, o construtor de configuração examinará apenas o nível superior do diretório.
  • optional - O valor padrão é false. Especifica se o construtor de configuração deve causar erros se o diretório de origem não existir.

Construtor de configuração simples

Aviso

Nunca armazene senhas, cadeias de conexão confidenciais ou outros dados confidenciais no código-fonte. Os segredos de produção não devem ser usados para desenvolvimento ou teste.

<add name="SimpleJson"
    [mode|prefix|stripPrefix|tokenPattern]
    jsonFile="~\config.json"
    [optional="true"]
    [jsonMode="(Flat|Sectional)"]
    type="Microsoft.Configuration.ConfigurationBuilders.SimpleJsonConfigBuilder,
    Microsoft.Configuration.ConfigurationBuilders.Json" />

Os projetos do .NET Core frequentemente usam arquivos JSON para configuração. O construtor SimpleJsonConfigBuilder permite que arquivos JSON do .NET Core sejam usados no .NET Framework. Esse construtor de configuração fornece um mapeamento básico de uma fonte de chave/valor simples para áreas específicas de chave/valor da configuração do .NET Framework. Esse construtor de configuração não fornece configurações hierárquicas. O arquivo de backup JSON é semelhante a um dicionário, não a um objeto hierárquico complexo. Um arquivo hierárquico de vários níveis pode ser usado. Esse provedor flattené a profundidade acrescentando o nome da propriedade em cada nível usando : como um delimitador.

Detalhes do atributo:

  • jsonFile - Obrigatório. Especifica o arquivo JSON do qual ler. O ~ caractere pode ser usado no início para fazer referência à raiz do aplicativo.

  • optional - Booleano, o valor padrão é true. Impede o lançamento de exceções se o arquivo JSON não puder ser encontrado.

  • jsonMode - [Flat|Sectional]. Flat é o padrão. Quando jsonMode é Flat, o arquivo JSON é uma única fonte de chave/valor simples. Os EnvironmentConfigBuilder e AzureKeyVaultConfigBuilder também são fontes únicas de chave/valor simples. Quando o SimpleJsonConfigBuilder está configurado no Sectional modo:

    • O arquivo JSON é conceitualmente dividido apenas no nível superior em vários dicionários.
    • Cada um dos dicionários é aplicado apenas à seção de configuração que corresponde ao nome da propriedade de nível superior anexado a eles. Por exemplo:
    {
        "appSettings" : {
            "setting1" : "value1",
            "setting2" : "value2",
            "complex" : {
                "setting1" : "complex:value1",
                "setting2" : "complex:value2",
            }
        }
    }

Ordem dos construtores de configuração

Consulte Ordem de execução de ConfigurationBuilders no repositório GitHub aspnet/MicrosoftConfigurationBuilders .

Implementando um construtor de configuração de chave/valor personalizado

Se os criadores de configuração não atenderem às suas necessidades, você poderá escrever um personalizado. A KeyValueConfigBuilder classe base lida com modos de substituição e a maioria das preocupações de prefixo. Um projeto de execução precisa apenas:

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" } };
    }
}

A KeyValueConfigBuilder classe base fornece grande parte do trabalho e do comportamento consistente entre os construtores de configuração de chave/valor.

Recursos adicionais