Almacenamiento seguro de secretos de aplicación en el desarrollo en ASP.NET Core

Nota:

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

Por Rick Anderson y Kirk Larkin

Vea o descargue el código de ejemplo (cómo descargarlo)

En este documento se explica cómo administrar los datos confidenciales de una aplicación de ASP.NET Core en un equipo de desarrollo. Nunca guarde las contraseñas u otros datos confidenciales en el código fuente. Los secretos de producción no se deben usar para desarrollo o prueba. Los secretos no se deben implementar con la aplicación. En su lugar, se debe acceder a los secretos de producción a través de un medio controlado, como variables de entorno o Azure Key Vault. Puede almacenar y proteger sus secretos de producción y pruebas de Azure con el proveedor de configuración de Azure Key Vault.

Para usar los secretos de usuario en una aplicación de consola de .NET, consulte este problema de GitHub.

Variables de entorno

Las variables de entorno se usan para evitar el almacenamiento de secretos de aplicación en el código o en archivos de configuración local. Las variables de entorno invalidan los valores de configuración de todos los orígenes de configuración especificados anteriormente.

Considere una aplicación web ASP.NET Core en la que está habilitada la seguridad delas cuentas de usuario individuales. En el archivo del proyecto appsettings.json se incluye una cadena de conexión de base de datos predeterminada con la clave DefaultConnection. La cadena de conexión predeterminada es para LocalDB, que se ejecuta en modo de usuario y no requiere una contraseña. Durante la implementación de la aplicación, el valor de clave DefaultConnection se puede invalidar con el valor de una variable de entorno. La variable de entorno puede almacenar la cadena de conexión completa con credenciales confidenciales.

Advertencia

Las variables de entorno se almacenan generalmente en texto sin formato y sin cifrar. Si la máquina o el proceso están en peligro, las partes que no son de confianza pueden acceder a las variables de entorno. Es posible que se requieran medidas adicionales para evitar la divulgación de secretos de usuario.

El separador : no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __, el carácter de subrayado doble, tiene las siguientes características:

  • Es compatible con todas las plataformas. Por ejemplo, el separador : no es compatible con Bash, pero __ sí.
  • Se reemplaza automáticamente por un signo :.

Administrador de secretos

La herramienta Secret Manager almacena datos confidenciales durante el desarrollo de aplicaciones. En este contexto, un fragmento de datos confidenciales es un secreto de aplicación. Los secretos de aplicación se almacenan en una ubicación independiente del árbol del proyecto. Los secretos de la aplicación están asociados a un proyecto específico o se comparten entre varios proyectos. Los secretos de la aplicación no se comprueban en el control de código fuente.

Advertencia

La herramienta Secret Manager no cifra los secretos almacenados y no debe tratarse como un almacén de confianza. Tiene solo fines de desarrollo. Las claves y los valores se almacenan en un JSarchivo de configuración ON en el directorio del perfil de usuario.

Funcionamiento de la herramienta Secret Manager

La herramienta Secret Manager oculta los detalles de implementación, como dónde y cómo se almacenan los valores. Puede usar la herramienta sin conocer estos detalles de implementación. Los valores se almacenan en un archivo JSON en la carpeta de perfil de usuario del equipo local:

Ruta del sistema de archivos:

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

En las rutas de acceso de archivo anteriores, reemplace <user_secrets_id> por el valor UserSecretsId especificado en el archivo de proyecto.

No escriba un código que dependa de la ubicación o el formato de los datos guardados con la herramienta Administrador de secretos. Estos detalles de implementación pueden cambiar. Por ejemplo, los valores secretos no están cifrados, pero podrían estarlo en el futuro.

Habilitación del almacenamiento de secretos

La herramienta Secret Manager funciona con las opciones de configuración específicas del proyecto almacenadas en el perfil de usuario.

Uso de la CLI

La herramienta Administrador de secretos incluye un comando init. Para usar los secretos de usuario, ejecute los siguientes comandos en el directorio del proyecto:

dotnet user-secrets init

El comando anterior agrega un elemento UserSecretsId con un PropertyGroup del archivo del proyecto. De forma predeterminada, el texto interno de UserSecretsId es un GUID. El texto interno es arbitrario, pero es único para el proyecto.

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

Usar Visual Studio

En Visual Studio, haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Administrar secretos de usuario en el menú contextual. Este gesto agrega un elemento UserSecretsId, rellenado con un GUID, al archivo del proyecto.

Si GenerateAssemblyInfo es false

Si la generación de atributos de información de ensamblado está deshabilitada, agregue manualmente el UserSecretsIdAttribute en AssemblyInfo.cs. Por ejemplo:

[assembly: UserSecretsId("your_user_secrets_id")]

Al agregar manualmente el atributo UserSecretsId a AssemblyInfo.cs, el valor de UserSecretsId debe coincidir con el valor del archivo del proyecto.

Establecimiento de un secreto

Defina un secreto de aplicación que consta de una clave y su valor. El secreto está asociado al valor UserSecretsId del proyecto. Por ejemplo, ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

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

En el ejemplo anterior, los dos puntos indican que Movies es un literal de objeto con una propiedad ServiceApiKey.

La herramienta Secret Manager también se puede usar desde otros directorios. Use la opción --project para proporcionar la ruta de acceso del sistema de archivos en la que existe el archivo del proyecto. Por ejemplo:

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

Acoplamiento de estructura JSON en Visual Studio

El gesto Administrar secretos de usuario de Visual Studio abre un archivo secrets.json en el editor de texto. Reemplace el contenido de secrets.json por los pares clave-valor que se van a almacenar. Por ejemplo:

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

La estructura JSON se aplana después de modificaciones a través de dotnet user-secrets remove o dotnet user-secrets set. Por ejemplo, ejecutar dotnet user-secrets remove "Movies:ConnectionString" contrae el literal de objeto Movies. El archivo modificado es similar al siguiente JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Establecimiento de varios secretos

Un lote de secretos se puede establecer mediante la canalización de JSON al comando set. En el ejemplo siguiente, el contenido del archivo input.json se canaliza al comando set.

Abra un shell de comandos y escriba el siguiente comando:

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

Acceder a un secreto

Para acceder a un secreto, complete los pasos siguientes:

  1. Registre el origen de configuración de los secretos de usuario
  2. Lea el secreto a través de la API de configuración

Registre el origen de configuración de secretos de usuario

El proveedor de configuración de secretos de usuario registra el origen de configuración adecuado con la API de configuración de .NET.

Las aplicaciones web de ASP.NET Core creadas con dotnet new o con Visual Studio generan el código siguiente:

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

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

app.Run();

WebApplication.CreateBuilder inicializa una nueva instancia de la clase WebApplicationBuilder con valores predeterminados preconfigurados. El inicializado WebApplicationBuilder (builder) proporciona la configuración predeterminada y llama a AddUserSecrets cuando EnvironmentName es Development:

Lea el secreto a través de la API de configuración

Tenga en cuenta los ejemplos siguientes de lectura de la clave Movies:ServiceApiKey:

Archivo program.cs:

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

var app = builder.Build();

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

app.Run();

Razor Modelo de página de páginas:

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 más información, consulte Configuración en ASP.NET Core.

Asignación de secretos a un POCO

Asignar un literal de objeto completo a un POCO (una clase .NET simple con propiedades) es útil para agregar propiedades relacionadas.

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Para asignar los secretos anteriores a un POCO, use la característica de enlace de grafos de objetos de la API de configuración de .NET. El código siguiente se enlaza a un POCO personalizado MovieSettings y accede al valor de propiedad ServiceApiKey:

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

Los secretos Movies:ConnectionString y Movies:ServiceApiKey son asignados a las respectivas propiedades en MovieSettings:

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

    public string ServiceApiKey { get; set; }
}

Reemplazo de cadenas con secretos

El almacenamiento de contraseñas en texto sin formato no es seguro. Por ejemplo, una cadena de conexión de base de datos almacenada en appsettings.json puede incluir una contraseña para el usuario especificado:

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

Un enfoque más seguro es almacenar la contraseña como un secreto. Por ejemplo:

dotnet user-secrets set "DbPassword" "pass123"

Quite el par clave-valor Password de la cadena de conexión en appsettings.json. Por ejemplo:

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

El valor del secreto se puede establecer en la propiedad Password de un objeto SqlConnectionStringBuilder para completar la cadena de conexión:

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();

Enumera los secretos

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

dotnet user-secrets list

Se mostrará la siguiente salida:

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

En el ejemplo anterior, un signo de dos puntos en los nombres de las claves denota la jerarquía de objetos dentro de secrets.json.

Eliminación de un único secreto

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

dotnet user-secrets remove "Movies:ConnectionString"

El archivo de la aplicación secrets.json se modificó para quitar el par clave-valor asociado a la clave Movies:ConnectionString:

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

dotnet user-secrets list muestra el siguiente mensaje de advertencia:

Movies:ServiceApiKey = 12345

Eliminación de todos los secretos

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

dotnet user-secrets clear

Todos los secretos de usuario de la aplicación se han eliminado del archivo secrets.json:

{}

Al ejecutar dotnet user-secrets list se muestra el siguiente mensaje de advertencia:

No secrets configured for this application.

Administración de secretos de usuario con Visual Studio

Para administrar secretos de usuario en Visual Studio, haga clic con el botón derecho en el proyecto en el explorador de soluciones y seleccione Administrar secretos de usuario:

Visual Studio mostrando la adiministración de los secretos de usuario

Migración de secretos de usuario de ASP.NET Framework a ASP.NET Core

Consulte este problema de GitHub.

Secretos de usuario en aplicaciones que no son web

Los proyectos que tienen como destino Microsoft.NET.Sdk.Web incluyen automáticamente compatibilidad con secretos de usuario. Para los proyectos que tienen como destino Microsoft.NET.Sdk, como las aplicaciones de consola, instale explícitamente los paquetes NuGet de extensión de configuración y secretos de usuario.

Mediante PowerShell:

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

Mediante la CLI de .NET:

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

Una vez instalados los paquetes, inicialice el proyecto y establezca secretos de la misma manera que para una aplicación web. En el siguiente ejemplo se muestra una aplicación de consola que recupera el valor de un secreto que se estableció con la clave "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 adicionales

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

Vea o descargue el código de ejemplo (cómo descargarlo)

En este documento se explica cómo administrar los datos confidenciales de una aplicación de ASP.NET Core en un equipo de desarrollo. Nunca guarde las contraseñas u otros datos confidenciales en el código fuente. Los secretos de producción no se deben usar para desarrollo o prueba. Los secretos no se deben implementar con la aplicación. En su lugar, se debe acceder a los secretos de producción a través de un medio controlado, como variables de entorno o Azure Key Vault. Puede almacenar y proteger sus secretos de producción y pruebas de Azure con el proveedor de configuración de Azure Key Vault.

Variables de entorno

Las variables de entorno se usan para evitar el almacenamiento de secretos de aplicación en el código o en archivos de configuración local. Las variables de entorno invalidan los valores de configuración de todos los orígenes de configuración especificados anteriormente.

Considere una aplicación web ASP.NET Core en la que está habilitada la seguridad delas cuentas de usuario individuales. En el archivo del proyecto appsettings.json se incluye una cadena de conexión de base de datos predeterminada con la clave DefaultConnection. La cadena de conexión predeterminada es para LocalDB, que se ejecuta en modo de usuario y no requiere una contraseña. Durante la implementación de la aplicación, el valor de clave DefaultConnection se puede invalidar con el valor de una variable de entorno. La variable de entorno puede almacenar la cadena de conexión completa con credenciales confidenciales.

Advertencia

Las variables de entorno se almacenan generalmente en texto sin formato y sin cifrar. Si la máquina o el proceso están en peligro, las partes que no son de confianza pueden acceder a las variables de entorno. Es posible que se requieran medidas adicionales para evitar la divulgación de secretos de usuario.

El separador : no funciona con claves jerárquicas de variables de entorno en todas las plataformas. __, el carácter de subrayado doble, tiene las siguientes características:

  • Es compatible con todas las plataformas. Por ejemplo, el separador : no es compatible con Bash, pero __ sí.
  • Se reemplaza automáticamente por un signo :.

Administrador de secretos

La herramienta Secret Manager almacena datos confidenciales durante el desarrollo de aplicaciones. En este contexto, un fragmento de datos confidenciales es un secreto de aplicación. Los secretos de aplicación se almacenan en una ubicación independiente del árbol del proyecto. Los secretos de la aplicación están asociados a un proyecto específico o se comparten entre varios proyectos. Los secretos de la aplicación no se comprueban en el control de código fuente.

Advertencia

La herramienta Secret Manager no cifra los secretos almacenados y no debe tratarse como un almacén de confianza. Tiene solo fines de desarrollo. Las claves y los valores se almacenan en un JSarchivo de configuración ON en el directorio del perfil de usuario.

Funcionamiento de la herramienta Secret Manager

La herramienta Secret Manager oculta los detalles de implementación, como dónde y cómo se almacenan los valores. Puede usar la herramienta sin conocer estos detalles de implementación. Los valores se almacenan en un archivo JSON en la carpeta de perfil de usuario del equipo local:

Ruta del sistema de archivos:

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

En las rutas de acceso de archivo anteriores, reemplace <user_secrets_id> por el valor UserSecretsId especificado en el archivo de proyecto.

No escriba un código que dependa de la ubicación o el formato de los datos guardados con la herramienta Administrador de secretos. Estos detalles de implementación pueden cambiar. Por ejemplo, los valores secretos no están cifrados, pero podrían estarlo en el futuro.

Habilitación del almacenamiento de secretos

La herramienta Secret Manager funciona con las opciones de configuración específicas del proyecto almacenadas en el perfil de usuario.

La herramienta Administrador de secretos incluye un comando init en el SDK de .NET Core 3.0.100 o posterior. Para usar los secretos de usuario, ejecute los siguientes comandos en el directorio del proyecto:

dotnet user-secrets init

El comando anterior agrega un elemento UserSecretsId con un PropertyGroup del archivo del proyecto. De forma predeterminada, el texto interno de UserSecretsId es un GUID. El texto interno es arbitrario, pero es único para el proyecto.

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

En Visual Studio, haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Administrar secretos de usuario en el menú contextual. Este gesto agrega un elemento UserSecretsId, rellenado con un GUID, al archivo del proyecto.

Establecimiento de un secreto

Defina un secreto de aplicación que consta de una clave y su valor. El secreto está asociado al valor UserSecretsId del proyecto. Por ejemplo, ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

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

En el ejemplo anterior, los dos puntos indican que Movies es un literal de objeto con una propiedad ServiceApiKey.

La herramienta Secret Manager también se puede usar desde otros directorios. Use la opción --project para proporcionar la ruta de acceso del sistema de archivos en la que existe el archivo del proyecto. Por ejemplo:

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

Acoplamiento de estructura JSON en Visual Studio

El gesto Administrar secretos de usuario de Visual Studio abre un archivo secrets.json en el editor de texto. Reemplace el contenido de secrets.json por los pares clave-valor que se van a almacenar. Por ejemplo:

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

La estructura JSON se aplana después de modificaciones a través de dotnet user-secrets remove o dotnet user-secrets set. Por ejemplo, ejecutar dotnet user-secrets remove "Movies:ConnectionString" contrae el literal de objeto Movies. El archivo modificado es similar al siguiente JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Establecimiento de varios secretos

Un lote de secretos se puede establecer mediante la canalización de JSON al comando set. En el ejemplo siguiente, el contenido del archivo input.json se canaliza al comando set.

Abra un shell de comandos y escriba el siguiente comando:

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

Acceder a un secreto

Para acceder a un secreto, complete los pasos siguientes:

  1. Registre el origen de configuración de los secretos de usuario
  2. Lea el secreto a través de la API de configuración

Registre el origen de configuración de secretos de usuario

El proveedor de configuración de secretos de usuario registra el origen de configuración adecuado con la API de configuración de .NET.

El origen de configuración de los secretos de usuario se agrega automáticamente en modo de desarrollo cuando el proyecto llama a CreateDefaultBuilder. CreateDefaultBuilder llama a AddUserSecrets cuando EnvironmentName es Development:

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

Cuando no se llama a CreateDefaultBuilder, agregue el origen de configuración de los secretos de usuario explícitamente mediante una llamada a AddUserSecrets en ConfigureAppConfiguration. Llame a AddUserSecrets solo cuando la aplicación se ejecute en el entorno de desarrollo, como se muestra en el ejemplo siguiente:

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

Lea el secreto a través de la API de configuración

Si el origen de configuración de secretos de usuario está registrado, la API de configuración .NET puede leer los secretos. La inserción de constructores se puede usar para obtener acceso a la API de configuración .NET. Tenga en cuenta los ejemplos siguientes de lectura de la clave Movies:ServiceApiKey:

Clase Startup:

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

Razor Modelo de página de páginas:

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 obtener más información, consulte Configuración de acceso en Startup y Configuración de acceso en páginas Razor.

Asignación de secretos a un POCO

Asignar un literal de objeto completo a un POCO (una clase .NET simple con propiedades) es útil para agregar propiedades relacionadas.

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Para asignar los secretos anteriores a un POCO, use la característica de enlace de grafos de objetos de la API de configuración de .NET. El código siguiente se enlaza a un POCO personalizado MovieSettings y accede al valor de propiedad ServiceApiKey:

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

Los secretos Movies:ConnectionString y Movies:ServiceApiKey son asignados a las respectivas propiedades en MovieSettings:

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

    public string ServiceApiKey { get; set; }
}

Reemplazo de cadenas con secretos

El almacenamiento de contraseñas en texto sin formato no es seguro. Por ejemplo, una cadena de conexión de base de datos almacenada en appsettings.json puede incluir una contraseña para el usuario especificado:

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

Un enfoque más seguro es almacenar la contraseña como un secreto. Por ejemplo:

dotnet user-secrets set "DbPassword" "pass123"

Quite el par clave-valor Password de la cadena de conexión en appsettings.json. Por ejemplo:

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

El valor del secreto se puede establecer en la propiedad Password de un objeto SqlConnectionStringBuilder para completar la cadena de conexión:

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

Enumera los secretos

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

dotnet user-secrets list

Se mostrará la siguiente salida:

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

En el ejemplo anterior, un signo de dos puntos en los nombres de las claves denota la jerarquía de objetos dentro de secrets.json.

Eliminación de un único secreto

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

dotnet user-secrets remove "Movies:ConnectionString"

El archivo de la aplicación secrets.json se modificó para quitar el par clave-valor asociado a la clave MoviesConnectionString:

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

dotnet user-secrets list muestra el siguiente mensaje de advertencia:

Movies:ServiceApiKey = 12345

Eliminación de todos los secretos

Supongamos que el archivosecrets.json de la aplicación contiene los dos secretos siguientes:

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

Ejecute el siguiente comando desde el directorio en el que existe el archivo del proyecto:

dotnet user-secrets clear

Todos los secretos de usuario de la aplicación se han eliminado del archivo secrets.json:

{}

Al ejecutar dotnet user-secrets list se muestra el siguiente mensaje de advertencia:

No secrets configured for this application.

Administración de secretos de usuario con Visual Studio

Para administrar secretos de usuario en Visual Studio, haga clic con el botón derecho en el proyecto en el explorador de soluciones y seleccione Administrar secretos de usuario:

Visual Studio mostrando la adiministración de los secretos de usuario

Migración de secretos de usuario de ASP.NET Framework a ASP.NET Core

Consulte este problema de GitHub.

Secretos de usuario en aplicaciones que no son web

Los proyectos que tienen como destino Microsoft.NET.Sdk.Web incluyen automáticamente compatibilidad con secretos de usuario. Para los proyectos que tienen como destino Microsoft.NET.Sdk, como las aplicaciones de consola, instale explícitamente los paquetes NuGet de extensión de configuración y secretos de usuario.

Mediante PowerShell:

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

Mediante la CLI de .NET:

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

Una vez instalados los paquetes, inicialice el proyecto y establezca secretos de la misma manera que para una aplicación web. En el siguiente ejemplo se muestra una aplicación de consola que recupera el valor de un secreto que se estableció con la clave "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 adicionales