Cassaforte l'archiviazione dei segreti dell'app in fase di sviluppo in ASP.NET Core

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione ASP.NET Core 8.0 di questo articolo.

Di Rick Anderson e Kirk Larkin

Visualizzare o scaricare il codice di esempio (procedura per il download)

Questo documento illustra come gestire i dati sensibili per un'app ASP.NET Core in un computer di sviluppo. Non archiviare mai password o altri dati sensibili nel codice sorgente. I segreti di produzione non devono essere usati per lo sviluppo o il test. I segreti non devono essere distribuiti con l'app. È invece necessario accedere ai segreti di produzione tramite un mezzo controllato, ad esempio variabili di ambiente o Azure Key Vault. È possibile memorizzare e proteggere i segreti relativi al test e alla produzione di Azure usando il provider di configurazione di Azure Key Vault.

Per usare i segreti utente in un'app console .NET, vedere questo problema di GitHub.

Variabili di ambiente

Le variabili di ambiente vengono usate per evitare l'archiviazione dei segreti dell'app nel codice o nei file di configurazione locali. Le variabili di ambiente sostituiscono i valori di configurazione per tutte le origini di configurazione specificate in precedenza.

Si consideri un'app Web ASP.NET Core in cui è abilitata la sicurezza dei singoli account utente. Un database predefinito stringa di connessione è incluso nel file del appsettings.json progetto con la chiave DefaultConnection. Il stringa di connessione predefinito è per Local DB, che viene eseguito in modalità utente e non richiede una password. Durante la distribuzione dell'app, il DefaultConnection valore della chiave può essere sottoposto a override con il valore di una variabile di ambiente. La variabile di ambiente può archiviare il stringa di connessione completo con credenziali riservate.

Avviso

Le variabili di ambiente vengono in genere archiviate in testo normale e non crittografato. Se il computer o il processo è compromesso, è possibile accedere alle variabili di ambiente da parti non attendibili. Potrebbero essere necessarie misure aggiuntive per impedire la divulgazione dei segreti utente.

Il separatore : non funziona con le chiavi gerarchiche delle variabili di ambiente in tutte le piattaforme. __, il doppio carattere di sottolineatura, è:

  • Supportato da tutte le piattaforme. Ad esempio, il separatore : non è supportato da Bash, ma __ è supportato.
  • Sostituito automaticamente da un :

Secret Manager

Lo strumento Secret Manager archivia i dati sensibili durante lo sviluppo di applicazioni. In questo contesto, una parte di dati sensibili è un segreto dell'app. I segreti dell'app vengono archiviati in una posizione separata dall'albero del progetto. I segreti dell'app sono associati a un progetto specifico o condivisi tra diversi progetti. I segreti dell'app non vengono controllati nel controllo del codice sorgente.

Avviso

Lo strumento Secret Manager non crittografa i segreti archiviati e non deve essere considerato come archivio attendibile. È solo a scopo di sviluppo. Le chiavi e i valori vengono archiviati in un JSfile di configurazione ON nella directory del profilo utente.

Funzionamento dello strumento Secret Manager

Lo strumento Secret Manager nasconde i dettagli di implementazione, ad esempio dove e come vengono archiviati i valori. È possibile usare lo strumento senza conoscere questi dettagli di implementazione. I valori vengono archiviati in un JSfile ON nella cartella del profilo utente del computer locale:

Percorso del file system:

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

Nei percorsi di file precedenti sostituire <user_secrets_id> con il UserSecretsId valore specificato nel file di progetto.

Non scrivere codice che dipende dalla posizione o dal formato dei dati salvati con lo strumento Secret Manager. Questi dettagli di implementazione possono cambiare. Ad esempio, i valori dei segreti non sono crittografati, ma potrebbero essere in futuro.

Abilitare l'archiviazione privata

Lo strumento Secret Manager opera sulle impostazioni di configurazione specifiche del progetto archiviate nel profilo utente.

Usare l'interfaccia della riga di comando

Lo strumento Secret Manager include un init comando. Per usare i segreti utente, eseguire il comando seguente nella directory del progetto:

dotnet user-secrets init

Il comando precedente aggiunge un UserSecretsId elemento all'interno di un PropertyGroup file di progetto. Per impostazione predefinita, il testo interno di UserSecretsId è un GUID. Il testo interno è arbitrario, ma è univoco per il progetto.

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

Usare Visual Studio

In Visual Studio fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Gestisci segreti utente dal menu di scelta rapida. Questo movimento aggiunge un UserSecretsId elemento, popolato con un GUID, al file di progetto.

Se GenerateAssemblyInfo è false

Se la generazione degli attributi delle informazioni sull'assembly è disabilitata, aggiungere manualmente in UserSecretsIdAttributeAssemblyInfo.cs. Ad esempio:

[assembly: UserSecretsId("your_user_secrets_id")]

Quando si aggiunge manualmente l'attributo UserSecretsId a AssemblyInfo.cs, il UserSecretsId valore deve corrispondere al valore nel file di progetto.

Impostare un segreto

Definire un segreto dell'app costituito da una chiave e dal relativo valore. Il segreto è associato al valore del UserSecretsId progetto. Ad esempio, eseguire il comando seguente dalla directory in cui è presente il file di progetto:

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

Nell'esempio precedente i due punti indicano che Movies è un valore letterale oggetto con una ServiceApiKey proprietà .

Lo strumento Secret Manager può essere usato anche da altre directory. Usare l'opzione --project per specificare il percorso del file system in corrispondenza del quale esiste il file di progetto. Ad esempio:

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

JSStruttura ON flat in Visual Studio

Il movimento Gestisci segreti utente di Visual Studio apre un secrets.json file nell'editor di testo. Sostituire il contenuto di secrets.json con le coppie chiave-valore da archiviare. Ad esempio:

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

La JSstruttura ON viene appiattita dopo le modifiche tramite dotnet user-secrets remove o dotnet user-secrets set. Ad esempio, l'esecuzione dotnet user-secrets remove "Movies:ConnectionString" comprime il valore letterale dell'oggetto Movies . Il file modificato è simile al seguente JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Impostare più segreti

È possibile impostare un batch di segreti tramite JSpipe ON al set comando . Nell'esempio seguente il input.json contenuto del file viene inviato tramite pipe al set comando .

Aprire una shell dei comandi ed eseguire il comando seguente:

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

Accedere a un segreto

Per accedere a un segreto, completare la procedura seguente:

  1. Registrare l'origine di configurazione dei segreti utente
  2. Leggere il segreto tramite l'API di configurazione

Registrare l'origine di configurazione dei segreti utente

Il provider di configurazione dei segreti utente registra l'origine di configurazione appropriata con l'API di configurazione .NET.

Le app Web ASP.NET Core create con dotnet new o Visual Studio generano il codice seguente:

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

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

app.Run();

WebApplication.CreateBuilder inizializza una nuova istanza della classe WebApplicationBuilder con valori predefiniti preconfigurati. L'inizializzato WebApplicationBuilder (builder) fornisce la configurazione predefinita e chiama AddUserSecrets quando EnvironmentName è Development:

Leggere il segreto tramite l'API di configurazione

Si considerino gli esempi seguenti di lettura della Movies:ServiceApiKey chiave:

Program.cs file:

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

var app = builder.Build();

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

app.Run();

Razor Modello di pagina Pagine:

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

Per altre informazioni, vedere Configurazione in ASP.NET Core.

Eseguire il mapping dei segreti a poco

Il mapping di un intero valore letterale oggetto a poco (una semplice classe .NET con proprietà) è utile per l'aggregazione di proprietà correlate.

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Per eseguire il mapping dei segreti precedenti a poco, usare la funzionalità di associazione dell'oggetto grafico dell'API di configurazione .NET. Il codice seguente viene associato a un poco personalizzato MovieSettings e accede al valore della ServiceApiKey proprietà:

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

I Movies:ConnectionString segreti e Movies:ServiceApiKey vengono mappati alle rispettive proprietà in MovieSettings:

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

    public string ServiceApiKey { get; set; }
}

Sostituzione di stringhe con segreti

L'archiviazione delle password in testo normale non è sicura. Ad esempio, un database stringa di connessione archiviato in appsettings.json può includere una password per l'utente specificato:

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

Un approccio più sicuro consiste nell'archiviare la password come segreto. Ad esempio:

dotnet user-secrets set "DbPassword" "pass123"

Rimuovere la Password coppia chiave-valore dal stringa di connessione in appsettings.json. Ad esempio:

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

Il valore del segreto può essere impostato sulla proprietà di Password un SqlConnectionStringBuilder oggetto per completare il stringa di connessione:

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

Elencare i segreti

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Eseguire il comando seguente dalla directory in cui è presente il file di progetto:

dotnet user-secrets list

Viene visualizzato l'output seguente:

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

Nell'esempio precedente, i due punti nei nomi delle chiavi indicano la gerarchia di oggetti all'interno di secrets.json.

Rimuovere un singolo segreto

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Eseguire il comando seguente dalla directory in cui è presente il file di progetto:

dotnet user-secrets remove "Movies:ConnectionString"

Il file dell'app secrets.json è stato modificato per rimuovere la coppia chiave-valore associata alla Movies:ConnectionString chiave:

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

dotnet user-secrets list visualizza il messaggio seguente:

Movies:ServiceApiKey = 12345

Rimuovere tutti i segreti

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Eseguire il comando seguente dalla directory in cui è presente il file di progetto:

dotnet user-secrets clear

Tutti i segreti utente per l'app sono stati eliminati dal secrets.json file:

{}

In esecuzione dotnet user-secrets list viene visualizzato il messaggio seguente:

No secrets configured for this application.

Gestire i segreti utente con Visual Studio

Per gestire i segreti utente in Visual Studio, fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e selezionare Gestisci segreti utente:

Visual Studio showing Manage User Secrets

Migrazione dei segreti utente da ASP.NET Framework a ASP.NET Core

Vedere il problema in GitHub.

Segreti utente in applicazioni non Web

I progetti destinati Microsoft.NET.Sdk.Web automaticamente includono il supporto per i segreti utente. Per i progetti destinati Microsoft.NET.Sdka , ad esempio le applicazioni console, installare in modo esplicito i pacchetti NuGet dell'estensione di configurazione e dei segreti utente.

Tramite PowerShell:

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

Uso dell'interfaccia della riga di comando di .NET:

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

Dopo aver installato i pacchetti, inizializzare il progetto e impostare i segreti come per un'app Web. L'esempio seguente mostra un'applicazione console che recupera il valore di un segreto impostato con la chiave "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"]);
    }
}

Risorse aggiuntive

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

Visualizzare o scaricare il codice di esempio (procedura per il download)

Questo documento illustra come gestire i dati sensibili per un'app ASP.NET Core in un computer di sviluppo. Non archiviare mai password o altri dati sensibili nel codice sorgente. I segreti di produzione non devono essere usati per lo sviluppo o il test. I segreti non devono essere distribuiti con l'app. È invece necessario accedere ai segreti di produzione tramite un mezzo controllato, ad esempio variabili di ambiente o Azure Key Vault. È possibile memorizzare e proteggere i segreti relativi al test e alla produzione di Azure usando il provider di configurazione di Azure Key Vault.

Variabili di ambiente

Le variabili di ambiente vengono usate per evitare l'archiviazione dei segreti dell'app nel codice o nei file di configurazione locali. Le variabili di ambiente sostituiscono i valori di configurazione per tutte le origini di configurazione specificate in precedenza.

Si consideri un'app Web ASP.NET Core in cui è abilitata la sicurezza dei singoli account utente. Un database predefinito stringa di connessione è incluso nel file del appsettings.json progetto con la chiave DefaultConnection. Il stringa di connessione predefinito è per Local DB, che viene eseguito in modalità utente e non richiede una password. Durante la distribuzione dell'app, il DefaultConnection valore della chiave può essere sottoposto a override con il valore di una variabile di ambiente. La variabile di ambiente può archiviare il stringa di connessione completo con credenziali riservate.

Avviso

Le variabili di ambiente vengono in genere archiviate in testo normale e non crittografato. Se il computer o il processo è compromesso, è possibile accedere alle variabili di ambiente da parti non attendibili. Potrebbero essere necessarie misure aggiuntive per impedire la divulgazione dei segreti utente.

Il separatore : non funziona con le chiavi gerarchiche delle variabili di ambiente in tutte le piattaforme. __, il doppio carattere di sottolineatura, è:

  • Supportato da tutte le piattaforme. Ad esempio, il separatore : non è supportato da Bash, ma __ è supportato.
  • Sostituito automaticamente da un :

Secret Manager

Lo strumento Secret Manager archivia i dati sensibili durante lo sviluppo di applicazioni. In questo contesto, una parte di dati sensibili è un segreto dell'app. I segreti dell'app vengono archiviati in una posizione separata dall'albero del progetto. I segreti dell'app sono associati a un progetto specifico o condivisi tra diversi progetti. I segreti dell'app non vengono controllati nel controllo del codice sorgente.

Avviso

Lo strumento Secret Manager non crittografa i segreti archiviati e non deve essere considerato come archivio attendibile. È solo a scopo di sviluppo. Le chiavi e i valori vengono archiviati in un JSfile di configurazione ON nella directory del profilo utente.

Funzionamento dello strumento Secret Manager

Lo strumento Secret Manager nasconde i dettagli di implementazione, ad esempio dove e come vengono archiviati i valori. È possibile usare lo strumento senza conoscere questi dettagli di implementazione. I valori vengono archiviati in un JSfile ON nella cartella del profilo utente del computer locale:

Percorso del file system:

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

Nei percorsi di file precedenti sostituire <user_secrets_id> con il UserSecretsId valore specificato nel file di progetto.

Non scrivere codice che dipende dalla posizione o dal formato dei dati salvati con lo strumento Secret Manager. Questi dettagli di implementazione possono cambiare. Ad esempio, i valori dei segreti non sono crittografati, ma potrebbero essere in futuro.

Abilitare l'archiviazione privata

Lo strumento Secret Manager opera sulle impostazioni di configurazione specifiche del progetto archiviate nel profilo utente.

Lo strumento Secret Manager include un init comando in .NET Core SDK 3.0.100 o versione successiva. Per usare i segreti utente, eseguire il comando seguente nella directory del progetto:

dotnet user-secrets init

Il comando precedente aggiunge un UserSecretsId elemento all'interno di un PropertyGroup file di progetto. Per impostazione predefinita, il testo interno di UserSecretsId è un GUID. Il testo interno è arbitrario, ma è univoco per il progetto.

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

In Visual Studio fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Gestisci segreti utente dal menu di scelta rapida. Questo movimento aggiunge un UserSecretsId elemento, popolato con un GUID, al file di progetto.

Impostare un segreto

Definire un segreto dell'app costituito da una chiave e dal relativo valore. Il segreto è associato al valore del UserSecretsId progetto. Ad esempio, eseguire il comando seguente dalla directory in cui è presente il file di progetto:

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

Nell'esempio precedente i due punti indicano che Movies è un valore letterale oggetto con una ServiceApiKey proprietà .

Lo strumento Secret Manager può essere usato anche da altre directory. Usare l'opzione --project per specificare il percorso del file system in corrispondenza del quale esiste il file di progetto. Ad esempio:

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

JSStruttura ON flat in Visual Studio

Il movimento Gestisci segreti utente di Visual Studio apre un secrets.json file nell'editor di testo. Sostituire il contenuto di secrets.json con le coppie chiave-valore da archiviare. Ad esempio:

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

La JSstruttura ON viene appiattita dopo le modifiche tramite dotnet user-secrets remove o dotnet user-secrets set. Ad esempio, l'esecuzione dotnet user-secrets remove "Movies:ConnectionString" comprime il valore letterale dell'oggetto Movies . Il file modificato è simile al seguente JSON:

{
  "Movies:ServiceApiKey": "12345"
}

Impostare più segreti

È possibile impostare un batch di segreti tramite JSpipe ON al set comando . Nell'esempio seguente il input.json contenuto del file viene inviato tramite pipe al set comando .

Aprire una shell dei comandi ed eseguire il comando seguente:

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

Accedere a un segreto

Per accedere a un segreto, completare la procedura seguente:

  1. Registrare l'origine di configurazione dei segreti utente
  2. Leggere il segreto tramite l'API di configurazione

Registrare l'origine di configurazione dei segreti utente

Il provider di configurazione dei segreti utente registra l'origine di configurazione appropriata con l'API di configurazione .NET.

L'origine di configurazione dei segreti utente viene aggiunta automaticamente in modalità sviluppo quando il progetto chiama CreateDefaultBuilder. CreateDefaultBuilder chiama AddUserSecrets quando è EnvironmentNameDevelopment:

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

Quando CreateDefaultBuilder non viene chiamato, aggiungere l'origine di configurazione dei segreti utente in modo esplicito chiamando AddUserSecrets in ConfigureAppConfiguration. Chiamare AddUserSecrets solo quando l'app viene eseguita nell'ambiente di sviluppo, come illustrato nell'esempio seguente:

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

Leggere il segreto tramite l'API di configurazione

Se l'origine di configurazione dei segreti utente è registrata, l'API di configurazione .NET può leggere i segreti. L'inserimento del costruttore può essere usato per ottenere l'accesso all'API di configurazione .NET. Si considerino gli esempi seguenti di lettura della Movies:ServiceApiKey chiave:

Classe 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 Modello di pagina Pagine:

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

Per altre informazioni, vedere Configurazione di accesso in Configurazione di avvio e accesso in Razor Pagine.

Eseguire il mapping dei segreti a poco

Il mapping di un intero valore letterale oggetto a poco (una semplice classe .NET con proprietà) è utile per l'aggregazione di proprietà correlate.

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Per eseguire il mapping dei segreti precedenti a poco, usare la funzionalità di associazione dell'oggetto grafico dell'API di configurazione .NET. Il codice seguente viene associato a un poco personalizzato MovieSettings e accede al valore della ServiceApiKey proprietà:

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

I Movies:ConnectionString segreti e Movies:ServiceApiKey vengono mappati alle rispettive proprietà in MovieSettings:

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

    public string ServiceApiKey { get; set; }
}

Sostituzione di stringhe con segreti

L'archiviazione delle password in testo normale non è sicura. Ad esempio, un database stringa di connessione archiviato in appsettings.json può includere una password per l'utente specificato:

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

Un approccio più sicuro consiste nell'archiviare la password come segreto. Ad esempio:

dotnet user-secrets set "DbPassword" "pass123"

Rimuovere la Password coppia chiave-valore dal stringa di connessione in appsettings.json. Ad esempio:

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

Il valore del segreto può essere impostato sulla proprietà di Password un SqlConnectionStringBuilder oggetto per completare il stringa di connessione:

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

Elencare i segreti

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Eseguire il comando seguente dalla directory in cui è presente il file di progetto:

dotnet user-secrets list

Viene visualizzato l'output seguente:

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

Nell'esempio precedente, i due punti nei nomi delle chiavi indicano la gerarchia di oggetti all'interno di secrets.json.

Rimuovere un singolo segreto

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Eseguire il comando seguente dalla directory in cui è presente il file di progetto:

dotnet user-secrets remove "Movies:ConnectionString"

Il file dell'app secrets.json è stato modificato per rimuovere la coppia chiave-valore associata alla MoviesConnectionString chiave:

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

dotnet user-secrets list visualizza il messaggio seguente:

Movies:ServiceApiKey = 12345

Rimuovere tutti i segreti

Si supponga che il file dell'app secrets.json contenga i due segreti seguenti:

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

Eseguire il comando seguente dalla directory in cui è presente il file di progetto:

dotnet user-secrets clear

Tutti i segreti utente per l'app sono stati eliminati dal secrets.json file:

{}

In esecuzione dotnet user-secrets list viene visualizzato il messaggio seguente:

No secrets configured for this application.

Gestire i segreti utente con Visual Studio

Per gestire i segreti utente in Visual Studio, fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e selezionare Gestisci segreti utente:

Visual Studio showing Manage User Secrets

Migrazione dei segreti utente da ASP.NET Framework a ASP.NET Core

Vedere il problema in GitHub.

Segreti utente in applicazioni non Web

I progetti destinati Microsoft.NET.Sdk.Web automaticamente includono il supporto per i segreti utente. Per i progetti destinati Microsoft.NET.Sdka , ad esempio le applicazioni console, installare in modo esplicito i pacchetti NuGet dell'estensione di configurazione e dei segreti utente.

Tramite PowerShell:

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

Uso dell'interfaccia della riga di comando di .NET:

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

Dopo aver installato i pacchetti, inizializzare il progetto e impostare i segreti come per un'app Web. L'esempio seguente mostra un'applicazione console che recupera il valore di un segreto impostato con la chiave "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"]);
    }
}

Risorse aggiuntive