Začínáme s rozhraními API ochrany dat v ASP.NET Core

Ochrana dat se v podstatě skládá z následujících kroků:

  1. Vytvořte ochranu dat od zprostředkovatele ochrany dat.
  2. Volejte metodu Protect s daty, která chcete chránit.
  3. Volejte metodu Unprotect s daty, která chcete vrátit zpět do prostého textu.

Většina architektur a modelů aplikací, jako je ASP.NET Core nebo SignalR, už konfiguruje systém ochrany dat a přidá ho do kontejneru služby, ke kterému se přistupuje prostřednictvím injektáže závislostí. Následující ukázka ukazuje:

  • Konfigurace kontejneru služby pro injektáž závislostí a registrace zásobníku ochrany dat
  • Příjem zprostředkovatele ochrany dat prostřednictvím DI.
  • Vytvoření ochrany
  • Ochrana a následné zrušení ochrany dat
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!
 */

Při vytváření ochrany musíte zadat jeden nebo více řetězců účelu. Účelový řetězec poskytuje izolaci mezi spotřebiteli. Například ochrana vytvořená s účelovým řetězcem "zelená" by nemohla zrušit ochranu dat poskytovaná ochranou s účelem "fialové".

Tip

IDataProtectionProvider Instance a IDataProtector jsou bezpečné pro více volajících. Je zamýšleno, že jakmile komponenta získá odkaz na IDataProtector prostřednictvím volání CreateProtector, použije tento odkaz pro více volání a Protect Unprotect.

Volání Unprotect vyvolá kryptografickou výjimkuException, pokud chráněnou datovou část nelze ověřit nebo dešifrovat. Některé komponenty mohou chtít ignorovat chyby během nechráněných operací; Komponenta, která čte soubory cookie pro ověřování, může tuto chybu zpracovat a zacházet s žádostí, jako by vůbec neměla, cookie a ne přímo selhat požadavek. Komponenty, které chtějí toto chování, by měly konkrétně zachytit kryptografickou výjimku místo polykání všech výjimek.

Konfigurace vlastního úložiště pomocí AddOptions

Vezměte v úvahu následující kód, který používá poskytovatele služeb, protože implementace IXmlRepository má závislost na jednoúčelové službě:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    var sp = services.BuildServiceProvider();
    services.AddDataProtection()
      .AddKeyManagementOptions(o => o.XmlRepository = sp.GetService<IXmlRepository>());
}

Předchozí kód zaznamená následující upozornění:

Volání BuildServiceProvider z kódu aplikace vede k vytvoření další kopie jednoúčelových služeb. Zvažte alternativy, jako je například vkládání závislostí, jako jsou parametry konfigurace.

Následující kód poskytuje implementaci IXmlRepository bez nutnosti sestavovat poskytovatele služeb, a proto vytvářet další kopie singletonových služeb:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DataProtectionDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    // Register XmlRepository for data protection.
    services.AddOptions<KeyManagementOptions>()
    .Configure<IServiceScopeFactory>((options, factory) =>
    {
        options.XmlRepository = new CustomXmlRepository(factory);
    });

    services.AddRazorPages();
}

Předchozí kód odebere volání GetService a skryje IConfigureOptions<T>.

Následující kód ukazuje vlastní úložiště XML:

using CustomXMLrepo.Data;
using Microsoft.AspNetCore.DataProtection.Repositories;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

public class CustomXmlRepository : IXmlRepository
{
    private readonly IServiceScopeFactory factory;

    public CustomXmlRepository(IServiceScopeFactory factory)
    {
        this.factory = factory;
    }

    public IReadOnlyCollection<XElement> GetAllElements()
    {
        using (var scope = factory.CreateScope())
        {
            var context = scope.ServiceProvider.GetRequiredService<DataProtectionDbContext>();
            var keys = context.XmlKeys.ToList()
                .Select(x => XElement.Parse(x.Xml))
                .ToList();
            return keys;
        }
    }

    public void StoreElement(XElement element, string friendlyName)
    {
        var key = new XmlKey
        {
            Xml = element.ToString(SaveOptions.DisableFormatting)
        };

        using (var scope = factory.CreateScope())
        {
            var context = scope.ServiceProvider.GetRequiredService<DataProtectionDbContext>();
            context.XmlKeys.Add(key);
            context.SaveChanges();
        }
    }
}

Následující kód ukazuje XmlKey třída:

public class XmlKey
{
    public Guid Id { get; set; }
    public string Xml { get; set; }

    public XmlKey()
    {
        this.Id = Guid.NewGuid();
    }
}