Sichere Speicherung von App-Geheimnissen in der Entwicklung in ASP.net CoreSafe storage of app secrets in development in ASP.NET Core

Von Rick Anderson, Kirk Larkin, Daniel Rothund Scott AddieBy Rick Anderson, Kirk Larkin, Daniel Roth, and Scott Addie

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

Dieses Dokument erläutert Techniken zum Speichern und Abrufen von sensiblen Daten während der Entwicklung einer ASP.net Core-App auf einem Entwicklungs Computer.This document explains techniques for storing and retrieving sensitive data during development of an ASP.NET Core app on a development machine. Speichern Sie niemals Kenn Wörter oder andere sensible Daten im Quellcode.Never store passwords or other sensitive data in source code. Produktionsgeheimnisse sollten nicht für Entwicklungs-oder Testzwecke verwendet werden.Production secrets shouldn't be used for development or test. Geheimnisse sollten nicht mit der APP bereitgestellt werden.Secrets shouldn't be deployed with the app. Stattdessen sollten geheime Schlüssel in der Produktionsumgebung über eine kontrollierte Methode wie Umgebungsvariablen, Azure Key Vault usw. zur Verfügung gestellt werden. Sie können Azure-Test-und Produktionsgeheimnisse mit dem Azure Key Vault Konfigurations Anbietersspeichern und schützen.Instead, secrets should be made available in the production environment through a controlled means like environment variables, Azure Key Vault, etc. You can store and protect Azure test and production secrets with the Azure Key Vault configuration provider.

UmgebungsvariablenEnvironment variables

Umgebungsvariablen werden verwendet, um das Speichern von App-Geheimnissen im Code oder in lokalen Konfigurationsdateien zu vermeiden.Environment variables are used to avoid storage of app secrets in code or in local configuration files. Umgebungsvariablen überschreiben Konfigurationswerte für alle zuvor angegebenen Konfigurations Quellen.Environment variables override configuration values for all previously specified configuration sources.

Stellen Sie sich eine ASP.net Core Web-App vor, in der die Sicherheit einzelner Benutzerkonten aktiviert ist.Consider an ASP.NET Core web app in which Individual User Accounts security is enabled. Eine standardmäßige Daten bankverbindungs Zeichenfolge ist in der appsettings.js Datei des Projekts mit dem Schlüssel enthalten DefaultConnection .A default database connection string is included in the project's appsettings.json file with the key DefaultConnection. Die Standard Verbindungs Zeichenfolge ist für localdb, das im Benutzermodus ausgeführt wird und kein Kennwort erfordert.The default connection string is for LocalDB, which runs in user mode and doesn't require a password. Während der APP-Bereitstellung DefaultConnection kann der Schlüsselwert mit dem Wert einer Umgebungsvariablen überschrieben werden.During app deployment, the DefaultConnection key value can be overridden with an environment variable's value. In der Umgebungsvariablen kann die gesamte Verbindungs Zeichenfolge mit vertraulichen Anmelde Informationen gespeichert werden.The environment variable may store the complete connection string with sensitive credentials.

Warnung

Umgebungsvariablen werden im Allgemeinen in unverschlüsseltem, unverschlüsseltem Text gespeichert.Environment variables are generally stored in plain, unencrypted text. Wenn der Computer oder der Prozess kompromittiert ist, kann von nicht vertrauenswürdigen Parteien auf Umgebungsvariablen zugegriffen werden.If the machine or process is compromised, environment variables can be accessed by untrusted parties. Möglicherweise sind zusätzliche Maßnahmen erforderlich, um eine Offenlegung von Benutzer Geheimnissen zu verhindern.Additional measures to prevent disclosure of user secrets may be required.

Das Trennzeichen : funktioniert nicht auf allen Plattformen mit den hierarchischen Schlüsseln von Umgebungsvariablen.The : separator doesn't work with environment variable hierarchical keys on all platforms. Der doppelte Unterstrich __:__, the double underscore, is:

  • wird auf allen Plattformen unterstützt.Supported by all platforms. Das Trennzeichen : wird beispielsweise nicht von Bash unterstützt, __ hingegen schon.For example, the : separator is not supported by Bash, but __ is.
  • automatisch durch : ersetzt.Automatically replaced by a :

Secret ManagerSecret Manager

Das Secret Manager-Tool speichert vertrauliche Daten während der Entwicklung eines ASP.net Core Projekts.The Secret Manager tool stores sensitive data during the development of an ASP.NET Core project. In diesem Zusammenhang handelt es sich bei einem sensiblen Datenobjekt um einen geheimen App-Schlüssel.In this context, a piece of sensitive data is an app secret. App-Geheimnisse werden an einem anderen Speicherort als in der Projektstruktur gespeichert.App secrets are stored in a separate location from the project tree. Die geheimen App-Schlüssel sind einem bestimmten Projekt zugeordnet oder können für mehrere Projekte freigegeben werden.The app secrets are associated with a specific project or shared across several projects. Die geheimen App-Schlüssel werden nicht in die Quell Code Verwaltung eingechecktThe app secrets aren't checked into source control.

Warnung

Das Secret Manager-Tool verschlüsselt die gespeicherten geheimen Schlüssel nicht und sollte nicht als vertrauenswürdiger Speicher behandelt werden.The Secret Manager tool doesn't encrypt the stored secrets and shouldn't be treated as a trusted store. Dies ist nur für Entwicklungszwecke vorgesehen.It's for development purposes only. Die Schlüssel und Werte werden in einer JSON-Konfigurationsdatei im Benutzerprofil Verzeichnis gespeichert.The keys and values are stored in a JSON configuration file in the user profile directory.

So funktioniert das Secret Manager-ToolHow the Secret Manager tool works

Das Secret Manager-Tool abstrahiert die Implementierungsdetails, z. b. wo und wie die Werte gespeichert werden.The Secret Manager tool abstracts away the implementation details, such as where and how the values are stored. Sie können das Tool verwenden, ohne diese Implementierungsdetails kennen zu lernen.You can use the tool without knowing these implementation details. Die Werte werden in einer JSON-Konfigurationsdatei in einem vom System geschützten Benutzerprofil Ordner auf dem lokalen Computer gespeichert:The values are stored in a JSON configuration file in a system-protected user profile folder on the local machine:

Dateisystempfad:File system path:

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

Ersetzen Sie in den vorangehenden Dateipfaden <user_secrets_id> durch den Wert, der UserSecretsId in der csproj -Datei angegeben ist.In the preceding file paths, replace <user_secrets_id> with the UserSecretsId value specified in the .csproj file.

Schreiben Sie keinen Code, der vom Speicherort oder Format der mit dem Geheimnis-Manager-Tool gespeicherten Daten abhängt.Don't write code that depends on the location or format of data saved with the Secret Manager tool. Diese Implementierungsdetails können sich ändern.These implementation details may change. Die geheimen Werte sind z. b. nicht verschlüsselt, können aber in der Zukunft liegen.For example, the secret values aren't encrypted, but could be in the future.

Aktivieren der geheimen SpeicherungEnable secret storage

Das Secret Manager-Tool arbeitet mit projektspezifischen Konfigurationseinstellungen, die in Ihrem Benutzerprofil gespeichert sind.The Secret Manager tool operates on project-specific configuration settings stored in your user profile.

Das Secret Manager-Tool enthält einen init Befehl in .net Core SDK 3.0.100 oder höher.The Secret Manager tool includes an init command in .NET Core SDK 3.0.100 or later. Zum Verwenden von Benutzer Geheimnissen führen Sie den folgenden Befehl im Projektverzeichnis aus:To use user secrets, run the following command in the project directory:

dotnet user-secrets init

Mit dem vorangehenden Befehl wird ein- UserSecretsId Element in einer PropertyGroup der csproj -Datei hinzugefügt.The preceding command adds a UserSecretsId element within a PropertyGroup of the .csproj file. Standardmäßig ist der innere Text von UserSecretsId eine GUID.By default, the inner text of UserSecretsId is a GUID. Der innere Text ist willkürlich, aber für das Projekt eindeutig.The inner text is arbitrary, but is unique to the project.

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

Klicken Sie in Visual Studio mit der rechten Maustaste auf das Projekt in Projektmappen-Explorer, und wählen Sie im Kontextmenü die Option Benutzer Geheimnisse verwalten aus.In Visual Studio, right-click the project in Solution Explorer, and select Manage User Secrets from the context menu. Diese Geste fügt UserSecretsId der csproj -Datei ein-Element, das mit einer GUID aufgefüllt ist, hinzu.This gesture adds a UserSecretsId element, populated with a GUID, to the .csproj file.

Festlegen eines GeheimnissesSet a secret

Definieren Sie einen geheimen App-Schlüssel, der aus einem Schlüssel und seinem Wert besteht.Define an app secret consisting of a key and its value. Das Geheimnis wird dem Wert des Projekts zugeordnet UserSecretsId .The secret is associated with the project's UserSecretsId value. Führen Sie z. b. den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:For example, run the following command from the directory in which the .csproj file exists:

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

Im vorherigen Beispiel deutet der Doppelpunkt darauf hin, dass Movies Ein Objektliteral mit einer- ServiceApiKey Eigenschaft ist.In the preceding example, the colon denotes that Movies is an object literal with a ServiceApiKey property.

Das Secret Manager-Tool kann auch aus anderen Verzeichnissen verwendet werden.The Secret Manager tool can be used from other directories too. Verwenden Sie die- --project Option, um den Dateisystempfad anzugeben, in dem die csproj -Datei vorhanden ist.Use the --project option to supply the file system path at which the .csproj file exists. Zum Beispiel:For example:

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

Vereinfachen der JSON-Struktur in Visual StudioJSON structure flattening in Visual Studio

Die Geste " Benutzer Geheimnisse verwalten " von Visual Studio öffnet eine secrets.jsfür die Datei im Text-Editor.Visual Studio's Manage User Secrets gesture opens a secrets.json file in the text editor. Ersetzen Sie den Inhalt secrets.jsauf durch die zu speichernden Schlüssel-Wert-Paare.Replace the contents of secrets.json with the key-value pairs to be stored. Zum Beispiel:For example:

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

Die JSON-Struktur wird nach Änderungen über dotnet user-secrets remove oder vereinfacht dotnet user-secrets set .The JSON structure is flattened after modifications via dotnet user-secrets remove or dotnet user-secrets set. Beispielsweise wird durch dotnet user-secrets remove "Movies:ConnectionString" das Ausführen des Movies Objektliterals reduziert.For example, running dotnet user-secrets remove "Movies:ConnectionString" collapses the Movies object literal. Die geänderte Datei ähnelt der folgenden:The modified file resembles the following:

{
  "Movies:ServiceApiKey": "12345"
}

Festlegen mehrerer geheimer SchlüsselSet multiple secrets

Ein Batch geheimer Schlüssel kann durch die Weiterleitung von JSON an den Befehl festgelegt werden set .A batch of secrets can be set by piping JSON to the set command. Im folgenden Beispiel werden die input.jsfür den Inhalt der Datei an den Befehl weitergeleitet set .In the following example, the input.json file's contents are piped to the set command.

Öffnen Sie eine Befehlsshell, und führen Sie den folgenden Befehl aus:Open a command shell, and execute the following command:

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

Auf einen geheimen Schlüssel zugreifenAccess a secret

Die ASP.net Core-Konfigurations-API ermöglicht den Zugriff auf Geheimnisse geheimer Geheimnisse.The ASP.NET Core Configuration API provides access to Secret Manager secrets.

Die Konfigurations Quelle für Benutzer Geheimnisse wird automatisch im Entwicklungsmodus hinzugefügt, wenn das Projekt aufruft CreateDefaultBuilder , um eine neue Instanz des Hosts mit vorkonfigurierten Standardwerten zu initialisieren.The user secrets configuration source is automatically added in development mode when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults. CreateDefaultBuilderwird aufgerufen, AddUserSecrets wenn Folgendes EnvironmentName ist Development :CreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development:

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

Wenn CreateDefaultBuilder nicht aufgerufen wird, fügen Sie die Konfigurations Quelle für Benutzer Geheimnisse explizit hinzu, indem Sie aufrufen AddUserSecrets .When CreateDefaultBuilder isn't called, add the user secrets configuration source explicitly by calling AddUserSecrets. AddUserSecretsWird nur aufgerufen, wenn die app in der Entwicklungsumgebung ausgeführt wird, wie im folgenden Beispiel gezeigt:Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example:

var host = new HostBuilder()
    .ConfigureAppConfiguration((hostContext, builder) =>
    {
        // Add other providers for JSON, etc.

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

Benutzer Geheimnisse können über die API abgerufen werden Configuration :User secrets can be retrieved via the Configuration API:

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

Zuordnen von Geheimnissen zu einem pocoMap secrets to a POCO

Das Mapping eines gesamten Objektliterals zu einem poco (eine einfache .NET-Klasse mit-Eigenschaften) ist nützlich für das aggregierten von verknüpften Eigenschaften.Mapping an entire object literal to a POCO (a simple .NET class with properties) is useful for aggregating related properties.

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Um die vorangehenden geheimen Schlüssel einem poco zuzuordnen, verwenden Sie die Configuration Objekt Diagramm-Bindungs Funktion der API.To map the preceding secrets to a POCO, use the Configuration API's object graph binding feature. Der folgende Code bindet an ein benutzerdefiniertes MovieSettings poco und greift auf den- ServiceApiKey Eigenschafts Wert zu:The following code binds to a custom MovieSettings POCO and accesses the ServiceApiKey property value:

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

Die Movies:ConnectionString Movies:ServiceApiKey Geheimnisse und werden den entsprechenden Eigenschaften in zugeordnet MovieSettings :The Movies:ConnectionString and Movies:ServiceApiKey secrets are mapped to the respective properties in MovieSettings:

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

    public string ServiceApiKey { get; set; }
}

Zeichen folgen Ersetzung mit geheimen SchlüsselnString replacement with secrets

Das Speichern von Kenn Wörtern im Klartext ist unsicher.Storing passwords in plain text is insecure. Beispielsweise kann eine Daten bankverbindungs Zeichenfolge, die in appsettings.jsauf gespeichert ist, ein Kennwort für den angegebenen Benutzer enthalten:For example, a database connection string stored in appsettings.json may include a password for the specified user:

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

Ein sichereren Ansatz besteht darin, das Kennwort als geheimen Schlüssel zu speichern.A more secure approach is to store the password as a secret. Zum Beispiel:For example:

dotnet user-secrets set "DbPassword" "pass123"

Entfernen Sie das Password Schlüssel-Wert-Paar aus der Verbindungs Zeichenfolge in appsettings.js.Remove the Password key-value pair from the connection string in appsettings.json. Zum Beispiel:For example:

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

Der Wert des Geheimnisses kann für die-Eigenschaft eines-Objekts festgelegt werden SqlConnectionStringBuilder Password , um die Verbindungs Zeichenfolge abzuschließen:The secret's value can be set on a SqlConnectionStringBuilder object's Password property to complete the connection string:

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

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

Auflisten der geheimen SchlüsselList the secrets

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Führen Sie den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets list

Die folgende Ausgabe wird angezeigt:The following output appears:

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

Im vorherigen Beispiel gibt ein Doppelpunkt in den Schlüsselnamen die Objekthierarchie in secrets.jsan.In the preceding example, a colon in the key names denotes the object hierarchy within secrets.json.

Entfernen eines einzelnen geheimen SchlüsselsRemove a single secret

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Führen Sie den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets remove "Movies:ConnectionString"

Die secrets.jsfür die Datei der App wurde geändert, um das Schlüssel-Wert-Paar zu entfernen, das dem Schlüssel zugeordnet ist MoviesConnectionString :The app's secrets.json file was modified to remove the key-value pair associated with the MoviesConnectionString key:

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

dotnet user-secrets listzeigt die folgende Meldung an:dotnet user-secrets list displays the following message:

Movies:ServiceApiKey = 12345

Alle geheimen Schlüssel entfernenRemove all secrets

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Führen Sie den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets clear

Alle geheimen Benutzerschlüssel für die APP wurden aus dem secrets.js für die Datei gelöscht:All user secrets for the app have been deleted from the secrets.json file:

{}

Wird ausgeführt, wird dotnet user-secrets list die folgende Meldung angezeigt:Running dotnet user-secrets list displays the following message:

No secrets configured for this application.

Zusätzliche RessourcenAdditional resources

Von Rick Anderson, Daniel Rothund Scott AddieBy Rick Anderson, Daniel Roth, and Scott Addie

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

Dieses Dokument erläutert Techniken zum Speichern und Abrufen von sensiblen Daten während der Entwicklung einer ASP.net Core-App auf einem Entwicklungs Computer.This document explains techniques for storing and retrieving sensitive data during development of an ASP.NET Core app on a development machine. Speichern Sie niemals Kenn Wörter oder andere sensible Daten im Quellcode.Never store passwords or other sensitive data in source code. Produktionsgeheimnisse sollten nicht für Entwicklungs-oder Testzwecke verwendet werden.Production secrets shouldn't be used for development or test. Geheimnisse sollten nicht mit der APP bereitgestellt werden.Secrets shouldn't be deployed with the app. Stattdessen sollten geheime Schlüssel in der Produktionsumgebung über eine kontrollierte Methode wie Umgebungsvariablen, Azure Key Vault usw. zur Verfügung gestellt werden. Sie können Azure-Test-und Produktionsgeheimnisse mit dem Azure Key Vault Konfigurations Anbietersspeichern und schützen.Instead, secrets should be made available in the production environment through a controlled means like environment variables, Azure Key Vault, etc. You can store and protect Azure test and production secrets with the Azure Key Vault configuration provider.

UmgebungsvariablenEnvironment variables

Umgebungsvariablen werden verwendet, um das Speichern von App-Geheimnissen im Code oder in lokalen Konfigurationsdateien zu vermeiden.Environment variables are used to avoid storage of app secrets in code or in local configuration files. Umgebungsvariablen überschreiben Konfigurationswerte für alle zuvor angegebenen Konfigurations Quellen.Environment variables override configuration values for all previously specified configuration sources.

Stellen Sie sich eine ASP.net Core Web-App vor, in der die Sicherheit einzelner Benutzerkonten aktiviert ist.Consider an ASP.NET Core web app in which Individual User Accounts security is enabled. Eine standardmäßige Daten bankverbindungs Zeichenfolge ist in der appsettings.js Datei des Projekts mit dem Schlüssel enthalten DefaultConnection .A default database connection string is included in the project's appsettings.json file with the key DefaultConnection. Die Standard Verbindungs Zeichenfolge ist für localdb, das im Benutzermodus ausgeführt wird und kein Kennwort erfordert.The default connection string is for LocalDB, which runs in user mode and doesn't require a password. Während der APP-Bereitstellung DefaultConnection kann der Schlüsselwert mit dem Wert einer Umgebungsvariablen überschrieben werden.During app deployment, the DefaultConnection key value can be overridden with an environment variable's value. In der Umgebungsvariablen kann die gesamte Verbindungs Zeichenfolge mit vertraulichen Anmelde Informationen gespeichert werden.The environment variable may store the complete connection string with sensitive credentials.

Warnung

Umgebungsvariablen werden im Allgemeinen in unverschlüsseltem, unverschlüsseltem Text gespeichert.Environment variables are generally stored in plain, unencrypted text. Wenn der Computer oder der Prozess kompromittiert ist, kann von nicht vertrauenswürdigen Parteien auf Umgebungsvariablen zugegriffen werden.If the machine or process is compromised, environment variables can be accessed by untrusted parties. Möglicherweise sind zusätzliche Maßnahmen erforderlich, um eine Offenlegung von Benutzer Geheimnissen zu verhindern.Additional measures to prevent disclosure of user secrets may be required.

Das Trennzeichen : funktioniert nicht auf allen Plattformen mit den hierarchischen Schlüsseln von Umgebungsvariablen.The : separator doesn't work with environment variable hierarchical keys on all platforms. Der doppelte Unterstrich __:__, the double underscore, is:

  • wird auf allen Plattformen unterstützt.Supported by all platforms. Das Trennzeichen : wird beispielsweise nicht von Bash unterstützt, __ hingegen schon.For example, the : separator is not supported by Bash, but __ is.
  • automatisch durch : ersetzt.Automatically replaced by a :

Secret ManagerSecret Manager

Das Secret Manager-Tool speichert vertrauliche Daten während der Entwicklung eines ASP.net Core Projekts.The Secret Manager tool stores sensitive data during the development of an ASP.NET Core project. In diesem Zusammenhang handelt es sich bei einem sensiblen Datenobjekt um einen geheimen App-Schlüssel.In this context, a piece of sensitive data is an app secret. App-Geheimnisse werden an einem anderen Speicherort als in der Projektstruktur gespeichert.App secrets are stored in a separate location from the project tree. Die geheimen App-Schlüssel sind einem bestimmten Projekt zugeordnet oder können für mehrere Projekte freigegeben werden.The app secrets are associated with a specific project or shared across several projects. Die geheimen App-Schlüssel werden nicht in die Quell Code Verwaltung eingechecktThe app secrets aren't checked into source control.

Warnung

Das Secret Manager-Tool verschlüsselt die gespeicherten geheimen Schlüssel nicht und sollte nicht als vertrauenswürdiger Speicher behandelt werden.The Secret Manager tool doesn't encrypt the stored secrets and shouldn't be treated as a trusted store. Dies ist nur für Entwicklungszwecke vorgesehen.It's for development purposes only. Die Schlüssel und Werte werden in einer JSON-Konfigurationsdatei im Benutzerprofil Verzeichnis gespeichert.The keys and values are stored in a JSON configuration file in the user profile directory.

So funktioniert das Secret Manager-ToolHow the Secret Manager tool works

Das Secret Manager-Tool abstrahiert die Implementierungsdetails, z. b. wo und wie die Werte gespeichert werden.The Secret Manager tool abstracts away the implementation details, such as where and how the values are stored. Sie können das Tool verwenden, ohne diese Implementierungsdetails kennen zu lernen.You can use the tool without knowing these implementation details. Die Werte werden in einer JSON-Konfigurationsdatei in einem vom System geschützten Benutzerprofil Ordner auf dem lokalen Computer gespeichert:The values are stored in a JSON configuration file in a system-protected user profile folder on the local machine:

Dateisystempfad:File system path:

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

Ersetzen Sie in den vorangehenden Dateipfaden <user_secrets_id> durch den Wert, der UserSecretsId in der csproj -Datei angegeben ist.In the preceding file paths, replace <user_secrets_id> with the UserSecretsId value specified in the .csproj file.

Schreiben Sie keinen Code, der vom Speicherort oder Format der mit dem Geheimnis-Manager-Tool gespeicherten Daten abhängt.Don't write code that depends on the location or format of data saved with the Secret Manager tool. Diese Implementierungsdetails können sich ändern.These implementation details may change. Die geheimen Werte sind z. b. nicht verschlüsselt, können aber in der Zukunft liegen.For example, the secret values aren't encrypted, but could be in the future.

Aktivieren der geheimen SpeicherungEnable secret storage

Das Secret Manager-Tool arbeitet mit projektspezifischen Konfigurationseinstellungen, die in Ihrem Benutzerprofil gespeichert sind.The Secret Manager tool operates on project-specific configuration settings stored in your user profile.

Definieren Sie ein- UserSecretsId Element in einer-Datei der PropertyGroup csproj -Datei, um Benutzer Geheimnisse zu verwenden.To use user secrets, define a UserSecretsId element within a PropertyGroup of the .csproj file. Der innere Text von UserSecretsId ist willkürlich, aber für das Projekt eindeutig.The inner text of UserSecretsId is arbitrary, but is unique to the project. Entwickler generieren in der Regel eine GUID für das UserSecretsId .Developers typically generate a GUID for the UserSecretsId.

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

Tipp

Klicken Sie in Visual Studio mit der rechten Maustaste auf das Projekt in Projektmappen-Explorer, und wählen Sie im Kontextmenü die Option Benutzer Geheimnisse verwalten aus.In Visual Studio, right-click the project in Solution Explorer, and select Manage User Secrets from the context menu. Diese Geste fügt UserSecretsId der csproj -Datei ein-Element, das mit einer GUID aufgefüllt ist, hinzu.This gesture adds a UserSecretsId element, populated with a GUID, to the .csproj file.

Festlegen eines GeheimnissesSet a secret

Definieren Sie einen geheimen App-Schlüssel, der aus einem Schlüssel und seinem Wert besteht.Define an app secret consisting of a key and its value. Das Geheimnis wird dem Wert des Projekts zugeordnet UserSecretsId .The secret is associated with the project's UserSecretsId value. Führen Sie z. b. den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:For example, run the following command from the directory in which the .csproj file exists:

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

Im vorherigen Beispiel deutet der Doppelpunkt darauf hin, dass Movies Ein Objektliteral mit einer- ServiceApiKey Eigenschaft ist.In the preceding example, the colon denotes that Movies is an object literal with a ServiceApiKey property.

Das Secret Manager-Tool kann auch aus anderen Verzeichnissen verwendet werden.The Secret Manager tool can be used from other directories too. Verwenden Sie die- --project Option, um den Dateisystempfad anzugeben, in dem die csproj -Datei vorhanden ist.Use the --project option to supply the file system path at which the .csproj file exists. Zum Beispiel:For example:

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

Vereinfachen der JSON-Struktur in Visual StudioJSON structure flattening in Visual Studio

Die Geste " Benutzer Geheimnisse verwalten " von Visual Studio öffnet eine secrets.jsfür die Datei im Text-Editor.Visual Studio's Manage User Secrets gesture opens a secrets.json file in the text editor. Ersetzen Sie den Inhalt secrets.jsauf durch die zu speichernden Schlüssel-Wert-Paare.Replace the contents of secrets.json with the key-value pairs to be stored. Zum Beispiel:For example:

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

Die JSON-Struktur wird nach Änderungen über dotnet user-secrets remove oder vereinfacht dotnet user-secrets set .The JSON structure is flattened after modifications via dotnet user-secrets remove or dotnet user-secrets set. Beispielsweise wird durch dotnet user-secrets remove "Movies:ConnectionString" das Ausführen des Movies Objektliterals reduziert.For example, running dotnet user-secrets remove "Movies:ConnectionString" collapses the Movies object literal. Die geänderte Datei ähnelt der folgenden:The modified file resembles the following:

{
  "Movies:ServiceApiKey": "12345"
}

Festlegen mehrerer geheimer SchlüsselSet multiple secrets

Ein Batch geheimer Schlüssel kann durch die Weiterleitung von JSON an den Befehl festgelegt werden set .A batch of secrets can be set by piping JSON to the set command. Im folgenden Beispiel werden die input.jsfür den Inhalt der Datei an den Befehl weitergeleitet set .In the following example, the input.json file's contents are piped to the set command.

Öffnen Sie eine Befehlsshell, und führen Sie den folgenden Befehl aus:Open a command shell, and execute the following command:

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

Auf einen geheimen Schlüssel zugreifenAccess a secret

Die ASP.net Core-Konfigurations-API ermöglicht den Zugriff auf Geheimnisse geheimer Geheimnisse.The ASP.NET Core Configuration API provides access to Secret Manager secrets.

Wenn das Projekt .NET Framework als Ziel hat, installieren Sie die Microsoft.Extensions.Config-urung. Usersecrets -nuget-Paket.If your project targets .NET Framework, install the Microsoft.Extensions.Configuration.UserSecrets NuGet package.

In ASP.net Core 2,0 oder höher wird die Konfigurations Quelle "Benutzer Geheimnisse" automatisch im Entwicklungsmodus hinzugefügt, wenn das Projekt aufruft CreateDefaultBuilder , um eine neue Instanz des Hosts mit vorkonfigurierten Standardwerten zu initialisieren.In ASP.NET Core 2.0 or later, the user secrets configuration source is automatically added in development mode when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults. CreateDefaultBuilderwird aufgerufen, AddUserSecrets wenn Folgendes EnvironmentName ist Development :CreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

Wenn CreateDefaultBuilder nicht aufgerufen wird, fügen Sie die Konfigurations Quelle für Benutzer Geheimnisse explizit hinzu, indem Sie AddUserSecrets im- Startup Konstruktor aufrufen.When CreateDefaultBuilder isn't called, add the user secrets configuration source explicitly by calling AddUserSecrets in the Startup constructor. AddUserSecretsWird nur aufgerufen, wenn die app in der Entwicklungsumgebung ausgeführt wird, wie im folgenden Beispiel gezeigt:Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", 
                     optional: false, 
                     reloadOnChange: true)
        .AddEnvironmentVariables();

    if (env.IsDevelopment())
    {
        builder.AddUserSecrets<Startup>();
    }

    Configuration = builder.Build();
}

Benutzer Geheimnisse können über die API abgerufen werden Configuration :User secrets can be retrieved via the Configuration API:

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

Zuordnen von Geheimnissen zu einem pocoMap secrets to a POCO

Das Mapping eines gesamten Objektliterals zu einem poco (eine einfache .NET-Klasse mit-Eigenschaften) ist nützlich für das aggregierten von verknüpften Eigenschaften.Mapping an entire object literal to a POCO (a simple .NET class with properties) is useful for aggregating related properties.

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Um die vorangehenden geheimen Schlüssel einem poco zuzuordnen, verwenden Sie die Configuration Objekt Diagramm-Bindungs Funktion der API.To map the preceding secrets to a POCO, use the Configuration API's object graph binding feature. Der folgende Code bindet an ein benutzerdefiniertes MovieSettings poco und greift auf den- ServiceApiKey Eigenschafts Wert zu:The following code binds to a custom MovieSettings POCO and accesses the ServiceApiKey property value:

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

Die Movies:ConnectionString Movies:ServiceApiKey Geheimnisse und werden den entsprechenden Eigenschaften in zugeordnet MovieSettings :The Movies:ConnectionString and Movies:ServiceApiKey secrets are mapped to the respective properties in MovieSettings:

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

    public string ServiceApiKey { get; set; }
}

Zeichen folgen Ersetzung mit geheimen SchlüsselnString replacement with secrets

Das Speichern von Kenn Wörtern im Klartext ist unsicher.Storing passwords in plain text is insecure. Beispielsweise kann eine Daten bankverbindungs Zeichenfolge, die in appsettings.jsauf gespeichert ist, ein Kennwort für den angegebenen Benutzer enthalten:For example, a database connection string stored in appsettings.json may include a password for the specified user:

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

Ein sichereren Ansatz besteht darin, das Kennwort als geheimen Schlüssel zu speichern.A more secure approach is to store the password as a secret. Zum Beispiel:For example:

dotnet user-secrets set "DbPassword" "pass123"

Entfernen Sie das Password Schlüssel-Wert-Paar aus der Verbindungs Zeichenfolge in appsettings.js.Remove the Password key-value pair from the connection string in appsettings.json. Zum Beispiel:For example:

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

Der Wert des Geheimnisses kann für die-Eigenschaft eines-Objekts festgelegt werden SqlConnectionStringBuilder Password , um die Verbindungs Zeichenfolge abzuschließen:The secret's value can be set on a SqlConnectionStringBuilder object's Password property to complete the connection string:

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

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

Auflisten der geheimen SchlüsselList the secrets

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Führen Sie den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets list

Die folgende Ausgabe wird angezeigt:The following output appears:

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

Im vorherigen Beispiel gibt ein Doppelpunkt in den Schlüsselnamen die Objekthierarchie in secrets.jsan.In the preceding example, a colon in the key names denotes the object hierarchy within secrets.json.

Entfernen eines einzelnen geheimen SchlüsselsRemove a single secret

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Führen Sie den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets remove "Movies:ConnectionString"

Die secrets.jsfür die Datei der App wurde geändert, um das Schlüssel-Wert-Paar zu entfernen, das dem Schlüssel zugeordnet ist MoviesConnectionString :The app's secrets.json file was modified to remove the key-value pair associated with the MoviesConnectionString key:

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

Wird ausgeführt, wird dotnet user-secrets list die folgende Meldung angezeigt:Running dotnet user-secrets list displays the following message:

Movies:ServiceApiKey = 12345

Alle geheimen Schlüssel entfernenRemove all secrets

Nehmen Sie an, dass die Datei " Secrets. JSON " der APP die folgenden beiden geheimen Schlüssel enthält:Assume the app's secrets.json file contains the following two secrets:

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

Führen Sie den folgenden Befehl aus dem Verzeichnis aus, in dem die csproj -Datei vorhanden ist:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets clear

Alle geheimen Benutzerschlüssel für die APP wurden aus dem secrets.js für die Datei gelöscht:All user secrets for the app have been deleted from the secrets.json file:

{}

Wird ausgeführt, wird dotnet user-secrets list die folgende Meldung angezeigt:Running dotnet user-secrets list displays the following message:

No secrets configured for this application.

Zusätzliche RessourcenAdditional resources