Обзор потребительских API

Интерфейсы IDataProtectionProvider и IDataProtector являются базовыми интерфейсами, с помощью которых потребители используют систему защиты данных. Эти интерфейсы находятся в пакете Microsoft.AspNet.DataProtection.Interfaces.

IDataProtectionProvider

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

IDataProtector

Этот интерфейс возвращается при вызове CreateProtector, и этот интерфейс используют потребители, чтобы выполнять операции по защите данных.

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

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

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

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

При DI (внедрении зависимостей) компонент принимает в конструктор параметр IDataProtectionProvider, а система DI автоматически предоставляет сервис, когда создается экземпляр компонента.

Примечание

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

В следующем примере представлено три концепции:

  1. Добавление системы защиты данных в контейнер.
  2. Использование DI для получения экземпляра IDataProtectionProvider.
  3. Создание IDataProtector из IDataProtectionProvider и его использование для защиты и снятия защиты с данных.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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!
 */

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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, если защищенные данные нельзя верифицировать или расшифровать. Некоторые компоненты могут игнорировать ошибки во время операций по снятию защиты; компонент, который считывает куки аутентификации, может обработать эту ошибку и поработать с запросом, как будто у него вообще нет куки. Такие компоненты словят только исключение CryptographicException, а не все исключения.

Поделись хорошей новостью с друзьями!
Следи за новостями!