Panoramica delle API consumer per ASP.NET Core

Le IDataProtectionProvider interfacce e IDataProtector sono le interfacce di base attraverso le quali i consumer usano il sistema di protezione dei dati. Si trovano nel pacchetto Microsoft.AspNetCore.DataProtection.Abstractions .

IDataProtectionProvider

L'interfaccia del provider rappresenta la radice del sistema di protezione dei dati. Non può essere usato direttamente per proteggere o rimuovere la protezione dei dati. Al contrario, il consumer deve ottenere un riferimento a un oggetto IDataProtector chiamando IDataProtectionProvider.CreateProtector(purpose), dove scopo è una stringa che descrive il caso d'uso del consumer previsto. Per altre informazioni sulla finalità di questo parametro e su come scegliere un valore appropriato, vedere Stringhe di scopo.

IDataProtector

L'interfaccia di protezione viene restituita da una chiamata a CreateProtectored è questa interfaccia che i consumer possono usare per eseguire operazioni di protezione e protezione.

Per proteggere una parte di dati, passare i dati al Protect metodo . L'interfaccia di base definisce un metodo che converte byte[] -> byte[], ma esiste anche un overload (fornito come metodo di estensione) che converte string -> string. La sicurezza offerta dai due metodi è identica; lo sviluppatore deve scegliere quale overload è più conveniente per il loro caso d'uso. Indipendentemente dall'overload scelto, il valore restituito dal metodo Protect è ora protetto (con crittografia e manomissione) e l'applicazione può inviarlo a un client non attendibile.

Per rimuovere la protezione di una parte di dati protetta in precedenza, passare i dati protetti al Unprotect metodo . Sono disponibili overload basati su byte[]e basati su stringhe per praticità per gli sviluppatori. Se il payload protetto è stato generato da una chiamata precedente a Protect su questo stesso IDataProtectoroggetto , il Unprotect metodo restituirà il payload non protetto originale. Se il payload protetto è stato manomesso o è stato prodotto da un oggetto diverso IDataProtector, il Unprotect metodo genererà CryptographicException.

Il concetto di stesso rispetto ai diversi IDataProtector legami con il concetto di scopo. Se due IDataProtector istanze sono state generate dalla stessa radice IDataProtectionProvider , ma tramite stringhe di scopo diverse nella chiamata a IDataProtectionProvider.CreateProtector, vengono considerate protezioni diverse e una non sarà in grado di rimuovere la protezione dei payload generati dall'altro.

Utilizzo di queste interfacce

Per un componente compatibile con l'inserimento delle dipendenze, l'utilizzo previsto è che il componente accetta un IDataProtectionProvider parametro nel relativo costruttore e che il sistema di inserimento delle dipendenze fornisce automaticamente questo servizio quando viene creata un'istanza del componente.

Nota

Alcune applicazioni, ad esempio applicazioni console o ASP.NET applicazioni 4.x, potrebbero non essere consapevoli delle dipendenze, quindi non possono usare il meccanismo descritto qui. Per questi scenari, vedere il documento Scenari non di riconoscimento delle dipendenze per altre informazioni su come ottenere un'istanza di un IDataProtection provider senza passare attraverso l'inserimento delle dipendenze.

L'esempio seguente illustra tre concetti:

  1. Aggiungere il sistema di protezione dei dati al contenitore del servizio,

  2. Uso dell'inserimento delle dipendenze per ricevere un'istanza di un oggetto IDataProtectionProvidere

  3. Creazione di un oggetto IDataProtector da un oggetto IDataProtectionProvider e uso per proteggere e rimuovere la protezione dei dati.

App console

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!
 */

Applicazione Web

Chiamare AddDataProtection(IServiceCollection, Action<DataProtectionOptions>) in Program.cs:

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

Il codice evidenziato seguente illustra come usare IDataProtector in un controller:

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

Il pacchetto Microsoft.AspNetCore.DataProtection.Abstractions contiene un metodo GetDataProtector di estensione per praticità per gli sviluppatori. Incapsula come singola operazione sia il recupero di un oggetto IDataProtectionProvider dal provider di servizi che la chiamata IDataProtectionProvider.CreateProtectora . L'esempio seguente illustra l'utilizzo:

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

Suggerimento

Le istanze di IDataProtectionProvider e IDataProtector sono thread-safe per più chiamanti. È previsto che una volta che un componente ottiene un riferimento a un oggetto IDataProtector tramite una chiamata a CreateProtector, userà tale riferimento per più chiamate a Protect e Unprotect. Una chiamata a Unprotect genererà CryptographicException se il payload protetto non può essere verificato o decifrato. Alcuni componenti potrebbero voler ignorare gli errori durante le operazioni di rimozione della protezione; un componente che legge i cookie di autenticazione potrebbe gestire questo errore e considerare la richiesta come se non avesse affatto esito cookie negativo, anziché interrompere la richiesta in modo definitivo. I componenti che vogliono questo comportamento devono intercettare in modo specifico CryptographicException anziché ingoiare tutte le eccezioni.