Schlüsselspeicheranbieter in ASP.NET Core

Das Datenschutzsystem verwendet standardmäßig einen Erkennungsmechanismus, um zu bestimmen, wo kryptografische Schlüssel aufbewahrt werden sollen. Der Entwickler kann den Standard-Erkennungsmechanismus außer Kraft setzen und den Speicherort manuell festlegen.

Warnung

Wenn Sie einen expliziten Speicherort für die Schlüsselpersistenz angeben, deregistriert das Datenschutzsystem den Standardmechanismus für die Schlüsselverschlüsselung im Ruhezustand, so dass die Schlüssel im Ruhezustand nicht mehr verschlüsselt werden. Es wird empfohlen, dass Sie zusätzlich einen expliziten Schlüsselverschlüsselungsmechanismus für die Produktionsbereitstellung angeben.

Dateisystem

Um ein dateisystembasiertes Schlüssel-Repository zu konfigurieren, rufen Sie die PersistKeysToFileSystem-Konfigurationsroutine wie unten gezeigt auf. Geben Sie einen DirectoryInfo an, das auf das Repository verweist, in dem die Schlüssel gespeichert werden sollen:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys\"));
}

DirectoryInfo kann auf ein Verzeichnis auf dem lokalen Rechner oder auf einen Ordner auf einer Netzwerkfreigabe verweisen. Wenn Sie auf ein Verzeichnis auf dem lokalen Rechner verweisen (und das Szenario ist, dass nur Anwendungen auf dem lokalen Rechner Zugriff auf dieses Repository benötigen), sollten Sie die Windows DPAPI (unter Windows) verwenden, um die Schlüssel im Ruhezustand zu verschlüsseln. Andernfalls sollten Sie ein X.509-Zertifikat für die Verschlüsselung von Schlüsseln im Ruhezustand verwenden.

Azure Storage

Das Paket Azure.Extensions.AspNetCore.DataProtection.Blobs ermöglicht die Speicherung von Datenschutzschlüsseln in Azure Blob Storage. Schlüssel können über mehrere Instanzen einer Webanwendung verteilt werden. Apps können Authentifizierungs-cookies oder CSRF-Schutz über mehrere Server hinweg gemeinsam nutzen.

Um den Azure Blob Storage Provider zu konfigurieren, rufen Sie eine der PersistKeysToAzureBlobStorage-Überladungen auf.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToAzureBlobStorage(new Uri("<blob URI including SAS token>"));
}

Wenn die Webanwendung als Azure-Dienst ausgeführt wird, kann die Verbindungszeichenfolge zur Authentifizierung beim Azure-Speicher verwendet werden, indem Sie Azure.Storage.Blobs verwenden.

string connectionString = "<connection_string>";
string containerName = "my-key-container";
string blobName = "keys.xml";
BlobContainerClient container = new BlobContainerClient(connectionString, containerName);

// optional - provision the container automatically
await container.CreateIfNotExistsAsync();

BlobClient blobClient = container.GetBlobClient(blobName);

services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(blobClient);

Hinweis

Die Verbindungszeichenfolge zu Ihrem Speicherkonto finden Sie im Azure-Portal unter dem Abschnitt „Zugriffsschlüssel“ oder indem Sie den folgenden CLI-Befehl ausführen:

az storage account show-connection-string --name <account_name> --resource-group <resource_group>

Redis

Das Paket Microsoft.AspNetCore.DataProtection.StackExchangeRedis ermöglicht die Speicherung von Datenschutzschlüsseln in einem Redis-Cache. Schlüssel können über mehrere Instanzen einer Webanwendung verteilt werden. Apps können Authentifizierungs-cookies oder CSRF-Schutz über mehrere Server hinweg gemeinsam nutzen.

Das Paket Microsoft.AspNetCore.DataProtection.Redis ermöglicht die Speicherung von Datenschutzschlüsseln in einem Redis-Cache. Schlüssel können über mehrere Instanzen einer Webanwendung verteilt werden. Apps können Authentifizierungs-cookies oder CSRF-Schutz über mehrere Server hinweg gemeinsam nutzen.

Um Redis zu konfigurieren, rufen Sie eine der PersistKeysToStackExchangeRedis-Überladungen auf:

public void ConfigureServices(IServiceCollection services)
{
    var redis = ConnectionMultiplexer.Connect("<URI>");
    services.AddDataProtection()
        .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
}

Um Redis zu konfigurieren, rufen Sie eine der PersistKeysToRedis-Überladungen auf:

public void ConfigureServices(IServiceCollection services)
{
    var redis = ConnectionMultiplexer.Connect("<URI>");
    services.AddDataProtection()
        .PersistKeysToRedis(redis, "DataProtection-Keys");
}

Weitere Informationen finden Sie in den folgenden Themen:

Registrierung

Gilt nur für Windows-Bereitstellungen.

Es kann vorkommen, dass die Anwendung keinen Schreibzugriff auf das Dateisystem hat. Stellen Sie sich ein Szenario vor, in dem eine Anwendung als virtuelles Dienstkonto ausgeführt wird (z. B. die App-Pool-Identität von w3wp.exe). In diesen Fällen kann der Administrator einen Registrierungsschlüssel bereitstellen, auf den die Identität des Dienstkontos zugreifen kann. Rufen Sie die Erweiterungsmethode PersistKeysToRegistry wie unten gezeigt auf. Geben Sie ein RegistryKey an, das auf den Ort verweist, an dem kryptografische Schlüssel gespeichert werden sollen:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Sample\keys", true));
}

Wichtig

Wir empfehlen die Verwendung von Windows DPAPI zur Verschlüsselung der Schlüssel im Ruhezustand.

Entity Framework Core

Das Paket Microsoft.AspNetCore.DataProtection.EntityFrameworkCore bietet einen Mechanismus zum Speichern von Datenschutzschlüsseln für eine Datenbank mit Entity Framework Core. Das NuGet-Paket Microsoft.AspNetCore.DataProtection.EntityFrameworkCore muss der Projektdatei hinzugefügt werden, es ist nicht Teil des Microsoft.AspNetCore.App Metapakets.

Mit diesem Paket können Schlüssel über mehrere Instanzen einer Webanwendung hinweg gemeinsam genutzt werden.

Um den EF Core-Anbieter zu konfigurieren, rufen Sie die PersistKeysToDbContext-Methode auf:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    // Add a DbContext to store your Database Keys
    services.AddDbContext<MyKeysContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("MyKeysConnection")));

    // using Microsoft.AspNetCore.DataProtection;
    services.AddDataProtection()
        .PersistKeysToDbContext<MyKeysContext>();

    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Wenn Sie möchten, dass Codekommentare in anderen Sprachen als Englisch angezeigt werden, informieren Sie uns in diesem GitHub-Issue.

Der generische Parameter TContext, muss von DbContext erben und IDataProtectionKeyContext implementieren:

using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;

namespace WebApp1
{
    class MyKeysContext : DbContext, IDataProtectionKeyContext
    {
        // A recommended constructor overload when using EF Core 
        // with dependency injection.
        public MyKeysContext(DbContextOptions<MyKeysContext> options) 
            : base(options) { }

        // This maps to the table that stores keys.
        public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
    }
}

Erstellen Sie die DataProtectionKeys-Tabelle.

Führen Sie die folgenden Befehle im Fenster Package Manager Console (PMC) aus:

Add-Migration AddDataProtectionKeys -Context MyKeysContext
Update-Database -Context MyKeysContext

MyKeysContext ist die im vorherigen Codebeispiel definierte DbContext. Wenn Sie einen DbContext mit einem anderen Namen verwenden, ersetzen Sie Ihren DbContext-Namen durch MyKeysContext.

Die Klasse/Entität DataProtectionKeys übernimmt die in der folgenden Tabelle dargestellte Struktur.

Eigenschaft/Feld CLR-Typ SQL-Typ
Id int int, PK, IDENTITY(1,1), nicht NULL
FriendlyName string nvarchar(MAX), NULL
Xml string nvarchar(MAX), NULL

Repository für benutzerdefinierte Schlüssel

Wenn die integrierten Mechanismen nicht geeignet sind, kann der Entwickler einen eigenen Mechanismus für die Schlüsselpersistenz festlegen, indem er ein benutzerdefiniertes IXmlRepository bereitstellt.