Armazenamento seguro de segredos do aplicativo em desenvolvimento no ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para obter a versão atual, confira a versão do ASP.NET Core 8.0 deste artigo.

Por Rick Anderson e Kirk Larkin

Exibir ou baixar código de exemplo (como baixar)

Este documento explica como gerenciar dados confidenciais de um aplicativo ASP.NET Core em um computador de desenvolvimento. Nunca armazene senhas ou outros dados confidenciais no código-fonte. Os segredos de produção não devem ser usados para desenvolvimento ou teste. Os segredos não devem ser implantados com o aplicativo. Em vez disso, os segredos de produção devem ser acessados por meio de um meio controlado, como variáveis de ambiente ou do Azure Key Vault. Você pode armazenar e proteger os segredos de teste e produção do Azure com o provedor de configuração do Azure Key Vault.

Para usar segredos de usuário em um aplicativo de console .NET, confira este problema do GitHub.

Variáveis de ambiente

As variáveis de ambiente são usadas para evitar o armazenamento de segredos de aplicativo no código ou em arquivos de configuração locais. As variáveis de ambiente substituem os valores de configuração de todas as fontes de configuração especificadas anteriormente.

Considere um aplicativo Web ASP.NET Core no qual a segurança de Contas de Usuário Individuais está habilitada. Uma cadeia de conexão de banco de dados padrão é incluída no arquivo appsettings.json do projeto com a chave DefaultConnection. A cadeia de conexão padrão é para LocalDB, que é executado no modo de usuário e não requer uma senha. Durante a implantação do aplicativo, o valor da chave DefaultConnection pode ser substituído pelo valor de uma variável de ambiente. A variável de ambiente pode armazenar a cadeia de conexão completa com credenciais confidenciais.

Aviso

Geralmente, as variáveis de ambiente são armazenadas em texto sem formatação e não criptografado. Se o computador ou o processo estiver comprometido, as variáveis de ambiente poderão ser acessadas por partes não confiáveis. Medidas adicionais para evitar a divulgação de segredos do usuário podem ser necessárias.

O separador : não funciona com chaves hierárquicas de variáveis de ambiente em todas as plataformas. __, o sublinhado duplo, tem:

  • Suporte em todas as plataformas. Por exemplo, o separador : não tem suporte pelo Bash, mas pelo __ tem.
  • Substituição automática por um :

Gerenciador de Segredos

A ferramenta Gerenciador Secreto armazena dados confidenciais durante o desenvolvimento do aplicativo. Nesse contexto, uma parte dos dados confidenciais é um segredo do aplicativo. Os segredos do aplicativo são armazenados em um local separado da árvore do projeto. Os segredos do aplicativo são associados a um projeto específico ou compartilhados em vários projetos. Os segredos do aplicativo não são verificados no controle do código-fonte.

Aviso

A ferramenta Gerenciador de Segredos não criptografa os segredos armazenados e não deve ser tratada como um repositório confiável. Serve apenas para fins de desenvolvimento. As chaves e os valores são armazenados em um arquivo de configuração JSON no diretório de perfil do usuário.

Como funciona a ferramenta Gerenciador de Segredos

A ferramenta Gerenciador de Segredos oculta os detalhes da implementação, como onde e como os valores são armazenados. Você pode usar a ferramenta sem saber esses detalhes de implementação. Os valores são armazenados em um arquivo JSON na pasta de perfil de usuário do computador local:

Caminho do sistema de arquivos:

%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json

Nos caminhos de arquivo anteriores, substitua <user_secrets_id> pelo valor UserSecretsId especificado no arquivo de projeto.

Não escreva códigos que dependam do local ou do formato dos dados salvos com a ferramenta Gerenciador de Segredos. Esses detalhes de implementação podem ser alterados. Por exemplo, os valores secretos não são criptografados, mas poderão ser no futuro.

Habilitar o armazenamento de segredos

A ferramenta Gerenciador de Segredos opera com definições de configuração específicas do projeto armazenadas em seu perfil de usuário.

Como usar a CLI

A ferramenta Gerenciador de Segredos inclui um comando init. Para usar os segredos de usuário, execute o seguinte comando no diretório do projeto:

dotnet user-secrets init

O comando anterior adiciona um elemento UserSecretsId dentro de um PropertyGroup do arquivo de projeto. Por padrão, o texto interno de UserSecretsId é um GUID. O texto interno é arbitrário, mas é exclusivo para o projeto.

<PropertyGroup>
  <TargetFramework>netcoreapp3.1</TargetFramework>
  <UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>

Usar o Visual Studio

No Visual Studio, clique com o botão direito do mouse no projeto no Gerenciador de Soluções e selecione Gerenciar Segredos de Usuário no menu de contexto. Esse gesto adiciona um elemento UserSecretsId, preenchido com um GUID, ao arquivo de projeto.

Se GenerateAssemblyInfo for false

Se a geração de atributos de informações do assembly estiver desabilitada, adicione manualmente o UserSecretsIdAttribute no AssemblyInfo.cs. Por exemplo:

[assembly: UserSecretsId("your_user_secrets_id")]

Ao adicionar manualmente o atributo UserSecretsId ao AssemblyInfo.cs, o valor UserSecretsId deve corresponder ao valor no arquivo de projeto.

Definir um segredo

Defina um segredo de aplicativo que consiste em uma chave e seu valor. O segredo está associado ao valor do projeto UserSecretsId. Por exemplo, execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets set "Movies:ServiceApiKey" "12345"

No exemplo anterior, os dois-pontos indicam que Movies é um literal de objeto com uma propriedade ServiceApiKey.

A ferramenta Gerenciador de Segredos também pode ser usada a partir de outros diretórios. Use a opção --project para fornecer o caminho do sistema de arquivos no qual o arquivo de projeto existe. Por exemplo:

dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"

Nivelamento da estrutura JSON no Visual Studio

O gesto Gerenciar Segredos do Usuário do Visual Studio abre um arquivo secrets.json no editor de texto. Substitua o conteúdo de secrets.json pelos pares chave-valor a serem armazenados. Por exemplo:

{
  "Movies": {
    "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
    "ServiceApiKey": "12345"
  }
}

A estrutura JSON é nivelada após modificações por meio de dotnet user-secrets remove ou dotnet user-secrets set. Por exemplo, a execução dotnet user-secrets remove "Movies:ConnectionString" recolhe o literal de objeto Movies. O arquivo modificado é semelhante ao seguinte JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Definir vários segredos

Um lote de segredos pode ser definido canalizando JSON para o comando set. No exemplo a seguir, o conteúdo do arquivo input.json é canalizado para o comando set.

Abra um shell de comando e execute o seguinte comando:

type .\input.json | dotnet user-secrets set

Acessar um segredo

Para acessar um segredo, conclua as seguintes etapas:

  1. Registrar a fonte de configuração de segredos do usuário
  2. Ler o segredo por meio da API de Configuração

Registrar a fonte de configuração de segredos do usuário

O provedor de configuração de segredos do usuário registra a fonte de configuração apropriada com a API de Configuração do .NET.

Os aplicativos Web ASP.NET Core criados com dotnet new ou Visual Studio geram o seguinte código:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

O WebApplication.CreateBuilder inicializa uma nova instância da classe WebApplicationBuilder com os padrões pré-configurados. O WebApplicationBuilder inicializado (builder) fornece configuração padrão e chama AddUserSecrets quando o EnvironmentName é Development:

Ler o segredo por meio da API de Configuração

Considere os seguintes exemplos de leitura da chave Movies:ServiceApiKey:

Arquivo program.cs:

var builder = WebApplication.CreateBuilder(args);
var movieApiKey = builder.Configuration["Movies:ServiceApiKey"];

var app = builder.Build();

app.MapGet("/", () => movieApiKey);

app.Run();

Modelo de página do Razor Pages:

public class IndexModel : PageModel
{
    private readonly IConfiguration _config;

    public IndexModel(IConfiguration config)
    {
        _config = config;
    }

    public void OnGet()
    {
        var moviesApiKey = _config["Movies:ServiceApiKey"];

        // call Movies service with the API key
    }
}

Para obter mais informações, consulte Configuração no ASP.NET Core.

Mapear segredos para um POCO

Mapear um literal de objeto inteiro para um POCO (uma classe .NET simples com propriedades) é útil para agregar propriedades relacionadas.

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Para mapear os segredos anteriores para um POCO, use o recurso de associação de grafo de objeto da API de Configuração do .NET. O código a seguir se associa a um POCO personalizado MovieSettings e acessa o valor da propriedade ServiceApiKey:

var moviesConfig = 
    Configuration.GetSection("Movies").Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;

Os segredos Movies:ConnectionString e Movies:ServiceApiKey são mapeados para as respectivas propriedades em MovieSettings:

public class MovieSettings
{
    public string ConnectionString { get; set; }

    public string ServiceApiKey { get; set; }
}

Substituição de cadeia de caracteres por segredos

Armazenar senhas em texto sem formatação não é seguro. Por exemplo, uma cadeia de conexão de banco de dados armazenada nas appsettings.json pode incluir uma senha para o usuário especificado:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;Password=pass123;MultipleActiveResultSets=true"
  }
}

Uma abordagem mais segura é armazenar a senha como um segredo. Por exemplo:

dotnet user-secrets set "DbPassword" "pass123"

Remova o par chave-valor Password da cadeia de conexão em appsettings.json. Por exemplo:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;MultipleActiveResultSets=true"
  }
}

O valor do segredo pode ser definido na propriedade Password do objeto SqlConnectionStringBuilder para concluir a cadeia de conexão:

using System.Data.SqlClient;

var builder = WebApplication.CreateBuilder(args);

var conStrBuilder = new SqlConnectionStringBuilder(
        builder.Configuration.GetConnectionString("Movies"));
conStrBuilder.Password = builder.Configuration["DbPassword"];
var connection = conStrBuilder.ConnectionString;

var app = builder.Build();

app.MapGet("/", () => connection);

app.Run();

Lista os segredos

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets list

O seguinte resultado é exibido:

Movies:ConnectionString = Server=(localdb)\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true
Movies:ServiceApiKey = 12345

No exemplo anterior, dois-pontos nos nomes das chaves denotam a hierarquia de objetos dentro de secrets.json.

Remover um único segredo

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets remove "Movies:ConnectionString"

O arquivo do aplicativo secrets.json foi modificado para remover o par chave-valor associado à chave Movies:ConnectionString:

{
  "Movies": {
    "ServiceApiKey": "12345"
  }
}

dotnet user-secrets list exibe a seguinte mensagem:

Movies:ServiceApiKey = 12345

Remover todos os segredos

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets clear

Todos os segredos do usuário para o aplicativo foram excluídos do arquivo secrets.json:

{}

Executar dotnet user-secrets list exibe a seguinte mensagem de aviso:

No secrets configured for this application.

Gerenciar segredos do usuário com o Visual Studio

Para gerenciar segredos de usuário no Visual Studio, clique com o botão direito do mouse no projeto no gerenciador de soluções e selecione Gerenciar Segredos de Usuário:

Visual Studio showing Manage User Secrets

Migrando segredos do usuário do ASP.NET Framework para o ASP.NET Core

Consulte este problema do GitHub.

Segredos do usuário em aplicativos não Web

Os projetos que têm como destino Microsoft.NET.Sdk.Web incluem automaticamente o suporte a segredos de usuário. Para projetos que têm como destino Microsoft.NET.Sdk, como aplicativos de console, instale explicitamente a extensão de configuração e os pacotes NuGet de segredos de usuário.

Usando o PowerShell:

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets

Usando a CLI do .NET:

dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets

Depois que os pacotes forem instalados, inicialize o projeto e defina segredos da mesma maneira que para um aplicativo Web. O exemplo a seguir mostra um aplicativo de console que recupera o valor de um segredo que foi definido com a chave "AppSecret":

using Microsoft.Extensions.Configuration;

namespace ConsoleApp;

class Program
{
    static void Main(string[] args)
    {
        IConfigurationRoot config = new ConfigurationBuilder()
            .AddUserSecrets<Program>()
            .Build();

        Console.WriteLine(config["AppSecret"]);
    }
}

Recursos adicionais

Por Rick Anderson, Kirk Larkin, Daniel Roth e Scott Addie

Exibir ou baixar código de exemplo (como baixar)

Este documento explica como gerenciar dados confidenciais de um aplicativo ASP.NET Core em um computador de desenvolvimento. Nunca armazene senhas ou outros dados confidenciais no código-fonte. Os segredos de produção não devem ser usados para desenvolvimento ou teste. Os segredos não devem ser implantados com o aplicativo. Em vez disso, os segredos de produção devem ser acessados por meio de um meio controlado, como variáveis de ambiente ou do Azure Key Vault. Você pode armazenar e proteger os segredos de teste e produção do Azure com o provedor de configuração do Azure Key Vault.

Variáveis de ambiente

As variáveis de ambiente são usadas para evitar o armazenamento de segredos de aplicativo no código ou em arquivos de configuração locais. As variáveis de ambiente substituem os valores de configuração de todas as fontes de configuração especificadas anteriormente.

Considere um aplicativo Web ASP.NET Core no qual a segurança de Contas de Usuário Individuais está habilitada. Uma cadeia de conexão de banco de dados padrão é incluída no arquivo appsettings.json do projeto com a chave DefaultConnection. A cadeia de conexão padrão é para LocalDB, que é executado no modo de usuário e não requer uma senha. Durante a implantação do aplicativo, o valor da chave DefaultConnection pode ser substituído pelo valor de uma variável de ambiente. A variável de ambiente pode armazenar a cadeia de conexão completa com credenciais confidenciais.

Aviso

Geralmente, as variáveis de ambiente são armazenadas em texto sem formatação e não criptografado. Se o computador ou o processo estiver comprometido, as variáveis de ambiente poderão ser acessadas por partes não confiáveis. Medidas adicionais para evitar a divulgação de segredos do usuário podem ser necessárias.

O separador : não funciona com chaves hierárquicas de variáveis de ambiente em todas as plataformas. __, o sublinhado duplo, tem:

  • Suporte em todas as plataformas. Por exemplo, o separador : não tem suporte pelo Bash, mas pelo __ tem.
  • Substituição automática por um :

Gerenciador de Segredos

A ferramenta Gerenciador Secreto armazena dados confidenciais durante o desenvolvimento do aplicativo. Nesse contexto, uma parte dos dados confidenciais é um segredo do aplicativo. Os segredos do aplicativo são armazenados em um local separado da árvore do projeto. Os segredos do aplicativo são associados a um projeto específico ou compartilhados em vários projetos. Os segredos do aplicativo não são verificados no controle do código-fonte.

Aviso

A ferramenta Gerenciador de Segredos não criptografa os segredos armazenados e não deve ser tratada como um repositório confiável. Serve apenas para fins de desenvolvimento. As chaves e os valores são armazenados em um arquivo de configuração JSON no diretório de perfil do usuário.

Como funciona a ferramenta Gerenciador de Segredos

A ferramenta Gerenciador de Segredos oculta os detalhes da implementação, como onde e como os valores são armazenados. Você pode usar a ferramenta sem saber esses detalhes de implementação. Os valores são armazenados em um arquivo JSON na pasta de perfil de usuário do computador local:

Caminho do sistema de arquivos:

%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json

Nos caminhos de arquivo anteriores, substitua <user_secrets_id> pelo valor UserSecretsId especificado no arquivo de projeto.

Não escreva códigos que dependam do local ou do formato dos dados salvos com a ferramenta Gerenciador de Segredos. Esses detalhes de implementação podem ser alterados. Por exemplo, os valores secretos não são criptografados, mas poderão ser no futuro.

Habilitar o armazenamento de segredos

A ferramenta Gerenciador de Segredos opera com definições de configuração específicas do projeto armazenadas em seu perfil de usuário.

A ferramenta Gerenciador de Segredos inclui um comando init no SDK do .NET Core 3.0.100 ou posterior. Para usar os segredos de usuário, execute o seguinte comando no diretório do projeto:

dotnet user-secrets init

O comando anterior adiciona um elemento UserSecretsId dentro de um PropertyGroup do arquivo de projeto. Por padrão, o texto interno de UserSecretsId é um GUID. O texto interno é arbitrário, mas é exclusivo para o projeto.

<PropertyGroup>
  <TargetFramework>netcoreapp3.1</TargetFramework>
  <UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>

No Visual Studio, clique com o botão direito do mouse no projeto no Gerenciador de Soluções e selecione Gerenciar Segredos de Usuário no menu de contexto. Esse gesto adiciona um elemento UserSecretsId, preenchido com um GUID, ao arquivo de projeto.

Definir um segredo

Defina um segredo de aplicativo que consiste em uma chave e seu valor. O segredo está associado ao valor do projeto UserSecretsId. Por exemplo, execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets set "Movies:ServiceApiKey" "12345"

No exemplo anterior, os dois-pontos indicam que Movies é um literal de objeto com uma propriedade ServiceApiKey.

A ferramenta Gerenciador de Segredos também pode ser usada a partir de outros diretórios. Use a opção --project para fornecer o caminho do sistema de arquivos no qual o arquivo de projeto existe. Por exemplo:

dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"

Nivelamento da estrutura JSON no Visual Studio

O gesto Gerenciar Segredos do Usuário do Visual Studio abre um arquivo secrets.json no editor de texto. Substitua o conteúdo de secrets.json pelos pares chave-valor a serem armazenados. Por exemplo:

{
  "Movies": {
    "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
    "ServiceApiKey": "12345"
  }
}

A estrutura JSON é nivelada após modificações por meio de dotnet user-secrets remove ou dotnet user-secrets set. Por exemplo, a execução dotnet user-secrets remove "Movies:ConnectionString" recolhe o literal de objeto Movies. O arquivo modificado é semelhante ao seguinte JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Definir vários segredos

Um lote de segredos pode ser definido canalizando JSON para o comando set. No exemplo a seguir, o conteúdo do arquivo input.json é canalizado para o comando set.

Abra um shell de comando e execute o seguinte comando:

type .\input.json | dotnet user-secrets set

Acessar um segredo

Para acessar um segredo, conclua as seguintes etapas:

  1. Registrar a fonte de configuração de segredos do usuário
  2. Ler o segredo por meio da API de Configuração

Registrar a fonte de configuração de segredos do usuário

O provedor de configuração de segredos do usuário registra a fonte de configuração apropriada com a API de Configuração do .NET.

A fonte de configuração de segredos do usuário é adicionada automaticamente no modo de Desenvolvimento quando o projeto chama CreateDefaultBuilder. CreateDefaultBuilder chama AddUserSecrets quando o EnvironmentName é Development:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Quando CreateDefaultBuilder não for chamado, adicione a fonte de configuração de segredos do usuário explicitamente chamando AddUserSecrets em ConfigureAppConfiguration. Chame AddUserSecrets somente quando o aplicativo for executado no ambiente de Desenvolvimento, conforme mostrado no exemplo a seguir:

public class Program
{
    public static void Main(string[] args)
    {
        var host = new HostBuilder()
            .ConfigureAppConfiguration((hostContext, builder) =>
            {
                // Add other providers for JSON, etc.

                if (hostContext.HostingEnvironment.IsDevelopment())
                {
                    builder.AddUserSecrets<Program>();
                }
            })
            .Build();
        
        host.Run();
    }
}

Ler o segredo por meio da API de Configuração

Se a fonte de configuração de segredos do usuário estiver registrada, a API de Configuração do .NET poderá ler os segredos. A injeção de construtor pode ser usada para obter acesso à API de Configuração do .NET. Considere os seguintes exemplos de leitura da chave Movies:ServiceApiKey:

Classe de inicialização:

public class Startup
{
    private string _moviesApiKey = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        _moviesApiKey = Configuration["Movies:ServiceApiKey"];
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            var result = string.IsNullOrEmpty(_moviesApiKey) ? "Null" : "Not Null";
            await context.Response.WriteAsync($"Secret is {result}");
        });
    }
}

Modelo de página do Razor Pages:

public class IndexModel : PageModel
{
    private readonly IConfiguration _config;

    public IndexModel(IConfiguration config)
    {
        _config = config;
    }

    public void OnGet()
    {
        var moviesApiKey = _config["Movies:ServiceApiKey"];

        // call Movies service with the API key
    }
}

Para obter mais informações, confira a Acessar configuração na Inicialização e Acessar configuração no Razor Pages.

Mapear segredos para um POCO

Mapear um literal de objeto inteiro para um POCO (uma classe .NET simples com propriedades) é útil para agregar propriedades relacionadas.

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Para mapear os segredos anteriores para um POCO, use o recurso de associação de grafo de objeto da API de Configuração do .NET. O código a seguir se associa a um POCO personalizado MovieSettings e acessa o valor da propriedade ServiceApiKey:

var moviesConfig = 
    Configuration.GetSection("Movies").Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;

Os segredos Movies:ConnectionString e Movies:ServiceApiKey são mapeados para as respectivas propriedades em MovieSettings:

public class MovieSettings
{
    public string ConnectionString { get; set; }

    public string ServiceApiKey { get; set; }
}

Substituição de cadeia de caracteres por segredos

Armazenar senhas em texto sem formatação não é seguro. Por exemplo, uma cadeia de conexão de banco de dados armazenada nas appsettings.json pode incluir uma senha para o usuário especificado:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;Password=pass123;MultipleActiveResultSets=true"
  }
}

Uma abordagem mais segura é armazenar a senha como um segredo. Por exemplo:

dotnet user-secrets set "DbPassword" "pass123"

Remova o par chave-valor Password da cadeia de conexão em appsettings.json. Por exemplo:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;MultipleActiveResultSets=true"
  }
}

O valor do segredo pode ser definido na propriedade Password do objeto SqlConnectionStringBuilder para concluir a cadeia de conexão:

public class Startup
{
    private string _connection = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        var builder = new SqlConnectionStringBuilder(
            Configuration.GetConnectionString("Movies"));
        builder.Password = Configuration["DbPassword"];
        _connection = builder.ConnectionString;

        // code omitted for brevity
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync($"DB Connection: {_connection}");
        });
    }
}

Lista os segredos

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets list

O seguinte resultado é exibido:

Movies:ConnectionString = Server=(localdb)\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true
Movies:ServiceApiKey = 12345

No exemplo anterior, dois-pontos nos nomes das chaves denotam a hierarquia de objetos dentro de secrets.json.

Remover um único segredo

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets remove "Movies:ConnectionString"

O arquivo do aplicativo secrets.json foi modificado para remover o par chave-valor associado à chave MoviesConnectionString:

{
  "Movies": {
    "ServiceApiKey": "12345"
  }
}

dotnet user-secrets list exibe a seguinte mensagem:

Movies:ServiceApiKey = 12345

Remover todos os segredos

Suponha que o arquivo secrets.json do aplicativo contenha os dois segredos a seguir:

{
  "Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "Movies:ServiceApiKey": "12345"
}

Execute o seguinte comando no diretório em que o arquivo de projeto está:

dotnet user-secrets clear

Todos os segredos do usuário para o aplicativo foram excluídos do arquivo secrets.json:

{}

Executar dotnet user-secrets list exibe a seguinte mensagem de aviso:

No secrets configured for this application.

Gerenciar segredos do usuário com o Visual Studio

Para gerenciar segredos de usuário no Visual Studio, clique com o botão direito do mouse no projeto no gerenciador de soluções e selecione Gerenciar Segredos de Usuário:

Visual Studio showing Manage User Secrets

Migrando segredos do usuário do ASP.NET Framework para o ASP.NET Core

Consulte este problema do GitHub.

Segredos do usuário em aplicativos não Web

Os projetos que têm como destino Microsoft.NET.Sdk.Web incluem automaticamente o suporte a segredos de usuário. Para projetos que têm como destino Microsoft.NET.Sdk, como aplicativos de console, instale explicitamente a extensão de configuração e os pacotes NuGet de segredos de usuário.

Usando o PowerShell:

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets

Usando a CLI do .NET:

dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets

Depois que os pacotes forem instalados, inicialize o projeto e defina segredos da mesma maneira que para um aplicativo Web. O exemplo a seguir mostra um aplicativo de console que recupera o valor de um segredo que foi definido com a chave "AppSecret":

using Microsoft.Extensions.Configuration;

namespace ConsoleApp;

class Program
{
    static void Main(string[] args)
    {
        IConfigurationRoot config = new ConfigurationBuilder()
            .AddUserSecrets<Program>()
            .Build();

        Console.WriteLine(config["AppSecret"]);
    }
}

Recursos adicionais