Обзор API-интерфейсов потребителей для ASP.NET Core

Интерфейсы IDataProtectionProviderIDataProtector это основные интерфейсы, через которые потребители используют систему защиты данных. Они находятся в пакете Microsoft.AspNetCore.DataProtection.Abstractions .

IDataProtectionProvider

Интерфейс поставщика представляет корень системы защиты данных. Его нельзя использовать напрямую для защиты или отмены защиты данных. Вместо этого потребитель должен получить ссылку на IDataProtector вызываемый IDataProtectionProvider.CreateProtector(purpose)метод, где цель — это строка, описывающая предполагаемый вариант использования потребителя. Дополнительные сведения о намерении этого параметра и выборе соответствующего значения см . в строках назначения.

IDataProtector

Интерфейс защиты возвращается вызовом CreateProtector, и это интерфейс, который потребители могут использовать для выполнения операций защиты и отмены защиты.

Чтобы защитить часть данных, передайте данные в Protect метод. Базовый интерфейс определяет метод, который преобразует байт[] -> байт[], но есть также перегрузка (предоставляемая в качестве метода расширения), которая преобразует строку -> string. Безопасность, предлагаемая двумя методами, идентична; Разработчик должен выбрать наиболее удобную перегрузку для своего варианта использования. Независимо от выбранной перегрузки, значение, возвращаемое методом Protect, теперь защищено (зашифровано и изменено), а приложение может отправить его ненадежным клиенту.

Чтобы отменить защиту ранее защищенного фрагмента данных, передайте защищенные данные в Unprotect метод. (Существуют байтовые и строковые перегрузки на основе строк для удобства разработчика.) Если защищенные полезные данные были созданы ранее вызовом этого же IDataProtectorвызоваProtect, Unprotect метод вернет исходную незащищенную полезные данные. Если защищенные полезные данные были изменены или были созданы другим IDataProtectorспособом, Unprotect метод вызовет CryptographicException.

Концепция одного и того же и другого IDataProtector отношения обратно к концепции цели. Если два IDataProtector экземпляра были созданы из одного корня IDataProtectionProvider , но с помощью разных строк назначения в вызове IDataProtectionProvider.CreateProtector, они считаются разными средствами защиты, и один не сможет отменить защиту полезных данных, созданных другим.

Использование этих интерфейсов

Для компонента с поддержкой di предполагаемое использование заключается в том, что компонент принимает IDataProtectionProvider параметр в конструкторе и что система DI автоматически предоставляет эту службу при создании экземпляра компонента.

Примечание.

Некоторые приложения (например, консольные приложения или приложения ASP.NET 4.x) могут не учитывать di-aware, поэтому не могут использовать механизм, описанный здесь. Для этих сценариев ознакомьтесь с документом о сценариях , не относящихся к DI, для получения дополнительных сведений о получении экземпляра поставщика без прохождения IDataProtection di.

В следующем примере показаны три понятия:

  1. Добавьте систему защиты данных в контейнер службы,

  2. Использование di для получения экземпляра объекта IDataProtectionProviderи

  3. IDataProtector Создание из нее IDataProtectionProvider и его использование для защиты и отмены защиты данных.

Консольное приложение

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

Веб-приложение

Вызов AddDataProtection(IServiceCollection, Action<DataProtectionOptions>) в Program.cs:

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

В следующем выделенном коде показано, как использовать IDataProtector в контроллере:

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

Пакет Microsoft.AspNetCore.DataProtection.Abstractions содержит метод GetDataProtector расширения в качестве удобства разработчика. Он инкапсулирует как одну операцию, извлекая IDataProtectionProvider из поставщика услуг и вызывая IDataProtectionProvider.CreateProtector. В следующем примере показано его использование:

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

Совет

Экземпляры IDataProtectionProvider и IDataProtector являются потокобезопасными для нескольких вызывающих объектов. Предполагается, что после того, как компонент получает ссылку на IDataProtector через вызов CreateProtector, он будет использовать такую ссылку для нескольких вызовов Protect и Unprotect. Вызов Unprotect вызовет вызов CryptographicException, если защищенные полезные данные не могут быть проверены или расшифрованы. Некоторые компоненты могут игнорировать ошибки во время незащищенных операций; компонент, который считывает проверку подлинности cookie, может обработать эту ошибку и обрабатывать запрос так, как если бы он не cookie имел вообще, а не завершился сбоем запроса. Компоненты, которые хотят, чтобы это поведение специально перехватывало CryptographicException, а не глотать все исключения.