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

Note

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

Warning

Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 10 de este artículo.

Por Rick Anderson y Kirk Larkin

En este artículo se explica cómo administrar datos confidenciales para una aplicación ASP.NET Core en una máquina de desarrollo. Nunca almacene contraseñas u otros datos confidenciales en archivos de configuración o 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. Se debe acceder a los secretos de producción a través de un medio controlado, como Azure Key Vault. Los secretos de prueba y producción de Azure se pueden almacenar y proteger con el proveedor de configuración de Azure Key Vault.

Ver o descargar el código de ejemplo (cómo descargar)

Para obtener más información sobre la autenticación para aplicaciones de prueba y producción implementadas, consulta Flujos de autenticación seguros.

Para usar secretos de usuario en una aplicación de consola de .NET, consulte GitHub problema dotnet/entityframework.docs #3939.

Trabajar con 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 de cuentas individuales . Se incluye una cadena de conexión de base de datos predeterminada en el archivo appsettings.json del proyecto 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 una aplicación, puede sobrescribir el valor de la clave DefaultConnection con el valor de una variable de entorno. La variable de entorno podría almacenar el cadena de conexión completo con credenciales confidenciales.

Warning

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

El separador de dos puntos (:) no funciona con las claves jerárquicas de variables de entorno en todas las plataformas. Por ejemplo, Bash no admite dos puntos (:) como separador. Todas las plataformas admiten la sintaxis de subrayado doble (__) y la reemplazan automáticamente por dos puntos (:).

Uso de la herramienta Administrador de secretos

Secret Manager es una herramienta que 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.
  • Están asociados a un proyecto específico o se comparten entre varios proyectos.
  • No están registrados en el control de código fuente.

Warning

Secret Manager no cifra los secretos almacenados y no se debe tratar como un almacén de confianza. Es solo para fines de desarrollo. Las claves y los valores se almacenan en un archivo de configuración JSON en el directorio del perfil de usuario.

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 de la máquina local:

Ruta del sistema de archivos:

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

En la ruta de acceso del sistema de archivos, reemplace la parte <user_secrets_id> por el valor UserSecretsId especificado en su archivo de proyecto.

No escriba código que dependa de la ubicación o el formato de los datos guardados con Secret Manager. Estos detalles de implementación pueden cambiar. Por ejemplo, los valores secretos no están cifrados.

Habilitación del almacenamiento de secretos

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

Uso de la CLI

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

dotnet user-secrets init

Este comando agrega un UserSecretsId elemento dentro de un PropertyGroup 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. En el ejemplo siguiente se muestra un valor GUID de 0000a1a1-b2b2-c3c3-d4d4-eeeeee555555.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <UserSecretsId>0000a1a1-b2b2-c3c3-d4d4-eeeeee555555</UserSecretsId>
  </PropertyGroup>

</Project>

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 del ensamblado (GenerateAssemblyInfo) está deshabilitada (establecida en false), agregue manualmente el elemento UserSecretsIdAttribute en el archivo AssemblyInfo.cs. Por ejemplo:

[assembly: UserSecretsId("your_user_secrets_id")]

Al agregar manualmente el UserSecretsId atributo al archivo AssemblyInfo.cs , el UserSecretsId valor 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 este ejemplo, los dos puntos indican que Movies es un literal de objeto con la propiedad ServiceApiKey.

También puede usar Secret Manager de otros directorios. Incluya la opción --project para indicar la ruta del sistema de archivos donde se encuentra el archivo del proyecto. Por ejemplo:

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

Aplanamiento de estructura JSON en Visual Studio

El gesto Visual Studio Administrar secretos de usuario abre un archivo secrets.json en el editor de texto. Reemplace el contenido del archivo 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 mediante el dotnet user-secrets remove comando o dotnet user-secrets set . Por ejemplo, al ejecutar dotnet user-secrets remove "Movies:ConnectionString", se contrae el objeto literal Movies. El archivo modificado es similar al siguiente JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Configurar 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 set comando .

Ejecute 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 secretos de usuario.

  2. Lea el secreto mediante 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 el comando dotnet new o con Visual Studio generan el siguiente código:

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

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

app.Run();

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

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

En los ejemplos siguientes se muestra cómo leer la Movies:ServiceApiKey clave:

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

Mapear secretos a un POCO

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

Supongamos que la aplicación secrets.json archivo 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; }
}

Usa el reemplazo de cadenas con secretos

El almacenamiento de contraseñas en texto sin formato no es seguro. No almacene nunca secretos en un archivo de configuración como appsettings.json, ya que podría terminar registrado en un repositorio de código fuente.

Por ejemplo, una cadena de conexión a una base de datos almacenada en un archivo appsettings.json no debe incluir una contraseña. En su lugar, almacene la contraseña como un secreto e incluya la contraseña en el cadena de conexión en tiempo de ejecución. Por ejemplo:

dotnet user-secrets set "DbPassword" "`<secret value>`"

Reemplace el <secret value> marcador de posición del ejemplo por el valor de contraseña. Establezca el valor del secreto en la propiedad SqlConnectionStringBuilder de un objeto Password para incluirlo como valor de contraseña en 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 la aplicación secrets.json archivo 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, dos puntos (:) en los nombres de clave denota la jerarquía de objetos dentro del archivo secrets.json .

Eliminación de un único secreto

Supongamos que la aplicación secrets.json archivo 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"

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

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

El dotnet user-secrets list comando muestra el siguiente mensaje:

Movies:ServiceApiKey = 12345

Eliminación de todos los secretos

Supongamos que la aplicación secrets.json archivo 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 eliminan del archivo secrets.json :

{}

Al ejecutar el comando dotnet user-secrets list, se muestra el siguiente mensaje:

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 Explorador de soluciones y seleccione Administrar secretos de usuario:

Screenshot muestra cómo seleccionar la opción Administrar secretos de usuario en Visual Studio.

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

Puede migrar los secretos de usuario almacenados de ASP.NET Framework a ASP.NET Core. Para obtener más información, consulte GitHub dotnet/aspnetcore.docs issue #27611 - La documentación de User Secrets no menciona la incompatibilidad con AssemblyInfo.cs.

Trabajar con 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.

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

Después de instalar los paquetes, inicialice el proyecto y establezca secretos de la misma manera que para una aplicación web. En el ejemplo siguiente se muestra una aplicación de consola que recupera el valor de un conjunto de secretos con la AppSecret clave :

using Microsoft.Extensions.Configuration;

namespace ConsoleApp;

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

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

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

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

En este artículo se explica cómo administrar datos confidenciales para una aplicación ASP.NET Core en una máquina de desarrollo. Nunca almacene contraseñas u otros datos confidenciales en archivos de configuración o 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. Se debe acceder a los secretos de producción a través de un medio controlado, como Azure Key Vault. Los secretos de prueba y producción de Azure se pueden almacenar y proteger con el proveedor de configuración de Azure Key Vault.

Para más información sobre la autenticación para entornos de prueba y producción, consulte Flujos de autenticación seguros.

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.

Warning

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 de dos puntos (:) no funciona con las claves jerárquicas de variables de entorno en todas las plataformas. Por ejemplo, Bash no admite dos puntos (:) como separador. Todas las plataformas admiten la sintaxis de subrayado doble (__) y la reemplazan automáticamente por dos puntos (:).

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.

Warning

La herramienta Secret Manager no cifra los secretos almacenados y no debe tratarse como un almacén de confianza. Es solo para fines de desarrollo. Las claves y los valores se almacenan en un archivo de configuración JSON 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 de la máquina 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 dentro de un PropertyGroup en el 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, el colon indica 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"

Aplanamiento 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 modificarse a través de dotnet user-secrets remove o dotnet user-secrets set. Por ejemplo, al ejecutar dotnet user-secrets remove "Movies:ConnectionString", se contrae el objeto literal Movies. El archivo modificado es similar al siguiente JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Configurar 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 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 explícitamente el origen de configuración de los secretos de usuario llamando a AddUserSecrets en ConfigureAppConfiguration. Llame AddUserSecrets solo cuando la aplicación se ejecute en el Development entorno, 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 de inicio:

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.

Mapear secretos a un POCO

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

Supongamos que la aplicación secrets.json archivo 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. Nunca almacene secretos en un archivo de configuración, como appsettings.json, que podría ser registrado en un repositorio de código fuente.

Por ejemplo, una base de datos cadena de conexión almacenada en appsettings.json no debe incluir una contraseña. En su lugar, almacene la contraseña como un secreto e incluya la contraseña en el cadena de conexión en tiempo de ejecución. Por ejemplo:

dotnet user-secrets set "DbPassword" "<secret value>"

Reemplace el <secret value> marcador de posición del ejemplo anterior por el valor de contraseña. Establezca el valor del secreto en la propiedad SqlConnectionStringBuilder de un objeto Password para incluirlo como valor de contraseña en 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 la aplicación secrets.json archivo 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 la aplicación secrets.json archivo 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 la aplicación secrets.json archivo 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 gestión de 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.

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