Übersicht der Consumer-APIs für ASP.NET Core

Die Schnittstellen IDataProtectionProvider und IDataProtector sind die grundlegenden Schnittstellen, über die Consumer das Datenschutzsystem nutzen. Sie befinden sich im Paket Microsoft.AspNetCore.DataProtection.Abstractions.

IDataProtectionProvider

Die Anbieterschnittstelle repräsentiert den Stamm des Datenschutzsystems. Sie kann nicht direkt zum Schützen oder Aufheben des Schutzes von Daten verwendet werden. Stattdessen muss der Consumer einen Verweis auf einen IDataProtector abrufen, indem er IDataProtectionProvider.CreateProtector(purpose) aufruft. Hierbei ist „purpose“ eine Zeichenfolge, die den beabsichtigten Anwendungsfall des Consumers beschreibt. Weitere Informationen über den Zweck dieses Parameters und die Auswahl eines geeigneten Werts finden Sie unter Zweckzeichenfolgen.

IDataProtector

Die Schutzvorrichtungsschnittstelle wird durch einen Aufruf von CreateProtector zurückgegeben. Über diese Schnittstelle können Consumer Vorgänge zum Schützen und Aufheben des Schutzes durchführen.

Zum Schutz von Daten übergeben Sie diese an die Methode Protect. Die Basisschnittstelle definiert eine Methode, die byte[] -> byte[] konvertiert, aber es gibt auch eine (als Erweiterungsmethode bereitgestellte) Überladung, die string -> string konvertiert. Beide Methoden bieten die gleiche Sicherheit. Entwickler*innen sollten sich für die Überladung entscheiden, die für ihren Anwendungsfall am besten geeignet ist. Unabhängig von der gewählten Überladung ist der von der Protect-Methode zurückgegebene Wert nun geschützt (verschlüsselt und manipulationssicher), und die Anwendung kann den Wert an einen nicht vertrauenswürdigen Client senden.

Um den Schutz von zuvor geschützten Daten aufzuheben, übergeben Sie die geschützten Daten an die Methode Unprotect. (Es werden byte[]-basierte und zeichenfolgenbasierte Überladungen bereitgestellt, um den Entwickler*innen die Arbeit zu erleichtern.) Wenn die geschützten Nutzdaten durch einen früheren Aufruf von Protect für denselben IDataProtector generiert wurden, gibt die Methode Unprotect die ursprünglichen ungeschützten Nutzdaten zurück. Wenn die geschützten Nutzdaten manipuliert oder durch einen anderen IDataProtector generiert wurden, löst die Methode Unprotect eine CryptographicException aus.

Das Konzept identischer vs. unterschiedlicher IDataProtector-Schnittstellen geht auf das Konzept des Zwecks zurück. Wenn zwei IDataProtector-Instanzen aus demselben Stamm IDataProtectionProvider, aber über unterschiedliche Zweckzeichenfolgen im Aufruf von IDataProtectionProvider.CreateProtector generiert wurden, dann gelten sie als unterschiedliche Schutzvorrichtungen und können den Schutz für die von der jeweils anderen Schutzvorrichtung generierten Nutzdaten nicht aufheben.

Nutzen dieser Schnittstellen

Für eine DI-fähige Komponente lautet die beabsichtigte Verwendung wie folgt: Die Komponente akzeptiert einen IDataProtectionProvider-Parameter in ihrem Konstruktor, und das DI-System stellt diesen Dienst automatisch bereit, wenn die Komponente instanziiert wird.

Hinweis

Einige Anwendungen (z. B. Konsolenanwendungen oder ASP.NET 4.x-Anwendungen) sind möglicherweise nicht DI-fähig und können den hier beschriebenen Mechanismus nicht verwenden. Für diese Szenarien finden Sie im Dokument Szenarien ohne Unterstützung der Abhängigkeitsinjektion weitere Informationen dazu, wie Sie eine Instanz eines IDataProtection-Anbieters ohne den Umweg über die Abhängigkeitsinjektion abrufen können.

Das folgende Beispiel veranschaulicht drei Konzepte:

  1. Hinzufügen des Datenschutzsystems zum Dienstcontainer

  2. Verwenden der Abhängigkeitsinjektion zum Empfangen einer Instanz von IDataProtectionProvider

  3. Erstellen eines IDataProtector aus einem IDataProtectionProvider und dessen Verwendung zum Schützen und Aufheben des Schutzes von Daten

Konsolen-App

using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
    public static void Main(string[] args)
    {
        // add data protection services
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection();
        var services = serviceCollection.BuildServiceProvider();

        // create an instance of MyClass using the service provider
        var instance = ActivatorUtilities.CreateInstance<MyClass>(services);
        instance.RunSample();
    }

    public class MyClass
    {
        IDataProtector _protector;

        // the 'provider' parameter is provided by DI
        public MyClass(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("Contoso.MyClass.v1");
        }

        public void RunSample()
        {
            Console.Write("Enter input: ");
            string input = Console.ReadLine();

            // protect the payload
            string protectedPayload = _protector.Protect(input);
            Console.WriteLine($"Protect returned: {protectedPayload}");

            // unprotect the payload
            string unprotectedPayload = _protector.Unprotect(protectedPayload);
            Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
        }
    }
}

/*
 * SAMPLE OUTPUT
 *
 * Enter input: Hello world!
 * Protect returned: CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ
 * Unprotect returned: Hello world!
 */

Web-App

Rufen Sie AddDataProtection(IServiceCollection, Action<DataProtectionOptions>) in Program.cs auf:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddDataProtection();

var app = builder.Build();

Der folgende hervorgehobene Code zeigt, wie Sie IDataProtector in einem Controller verwenden:

public class HomeController : Controller
{
    private readonly IDataProtector _dataProtector;

    public HomeController(IDataProtectionProvider dataProtectionProvider)
    {
        _dataProtector = dataProtectionProvider.CreateProtector("HomeControllerPurpose");
    }

    // ...

    public IActionResult Privacy()
    {
        // The original data to protect
        string originalData = "original data";

        // Protect the data (encrypt)
        string protectedData = _dataProtector.Protect(originalData);
        Console.WriteLine($"Protected Data: {protectedData}");

        // Unprotect the data (decrypt)
        string unprotectedData = _dataProtector.Unprotect(protectedData);
        Console.WriteLine($"Unprotected Data: {unprotectedData}");

        return View();
    }
    
    // ...

Das Paket Microsoft.AspNetCore.DataProtection.Abstractions enthält eine Erweiterungsmethode GetDataProtector, um den Entwickler*innen die Arbeit zu erleichtern. Sie kapselt in einem einzigen Vorgang sowohl den Abruf eines IDataProtectionProvider vom Dienstanbieter als auch den Aufruf von IDataProtectionProvider.CreateProtector. Das folgende Beispiel veranschaulicht ihre Verwendung:

using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
 
public class Program
{
    public static void Main(string[] args)
    {
        // add data protection services
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection();
        var services = serviceCollection.BuildServiceProvider();
 
        // get an IDataProtector from the IServiceProvider
        var protector = services.GetDataProtector("Contoso.Example.v2");
        Console.Write("Enter input: ");
        string input = Console.ReadLine();
 
        // protect the payload
        string protectedPayload = protector.Protect(input);
        Console.WriteLine($"Protect returned: {protectedPayload}");
 
        // unprotect the payload
        string unprotectedPayload = protector.Unprotect(protectedPayload);
        Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
    }
}

Tipp

Die Instanzen von IDataProtectionProvider und IDataProtector sind threadsicher für mehrere Aufrufer. Es ist beabsichtigt, dass eine Komponente, die über einen Aufruf von CreateProtector einen Verweis auf einen IDataProtector erhält, diesen Verweis für mehrere Aufrufe von Protect und Unprotect verwendet. Ein Aufruf von Unprotect führt zu einer CryptographicException, wenn die geschützten Nutzdaten nicht verifiziert oder entschlüsselt werden können. Für einige Komponenten kann es sinnvoll sein, Fehler beim Aufheben des Schutzes zu ignorieren. Eine Komponente, die Authentifizierungs-cookies liest, könnte diesen Fehler umgehen, indem die Anforderung so behandelt wird, als ob sie gar keine cookies enthielte, anstatt die Anforderung ganz abzulehnen. Komponenten, für die dieses Verhalten gewünscht wird, sollten speziell CryptographicExceptions abfangen, anstatt alle Ausnahmen zu verarbeiten.