Ограничение жизненного цикла защищенных данных

Существуют сценарии, когда разработчики хотят, чтобы данные перестали быть защищенными через некоторое время. Например, у нас может быть пароль, который валиден всего лишь один час. Разработчик может создать свой собственный формат, содержащий дату истечения пароля, и продвинутые разработчики могут это сделать, но для большинства это может быть сложным процессом.

У нас есть пакет Microsoft.AspNet.DataProtection.Extensions, содержащий API для создания данных, истечение защиты которых происходит через указанное время. Эти API связаны с типом ITimeLimitedDataProtector.

Использование API

Интерфейс ITimeLimitedDataProtector является основным интерфейсом для защиты и снятия защиты с данных с определенным сроком службы. Чтобы создать экземпляр ITimeLimitedDataProtector, вам сперва понадобится экземпляр обычного IDataProtector, созданного с конкретной строкой purpose. Когда экземпляр IDataProtector доступен, вызовите метод расширения IDataProtector.ToTimeLimitedDataProtector, чтобы получить механизм защиты со встроенными возможностями для реализации истечения срока службы.

ITimeLimitedDataProtector предлагает следующий API и методы расширения:

  • CreateProtector(string purpose) : ITimeLimitedDataProtector Этот API похож на существующий IDataProtectionProvider.CreateProtector в том, что его можно использовать для создания цепей purpose из корневого механизма защиты.
  • Protect(byte[] plaintext, DateTimeOffset expiration) : byte[]
  • Protect(byte[] plaintext, TimeSpan lifetime) : byte[]
  • Protect(byte[] plaintext) : byte[]
  • Protect(string plaintext, DateTimeOffset expiration) : string
  • Protect(string plaintext, TimeSpan lifetime) : string
  • Protect(string plaintext) : string

В дополнении к основным методам Protect, которые принимают только plaintext, есть перегруженные варианты, в которых можно указать истечение срока службы. Дату истечения срока можно указать как абсолютную дату (через DateTimeOffset) или относительное время (через TimeSpan). Если вызывается метод, где нельзя указать истечение срока службы, то считается, что истечение срока службы для этих данных никогда не наступит.

  • Unprotect(byte[] protectedData, out DateTimeOffset expiration) : byte[]
  • Unprotect(byte[] protectedData) : byte[]
  • Unprotect(string protectedData, out DateTimeOffset expiration) : string
  • Unprotect(string protectedData) : string

Методы Unprotect возвращают оригинальные незащищенные данные. Если срок службы еще не истек, возвращается абсолютный срок истечения в качестве дополнительного параметра наряду с оригинальными незащищенными данными. Если срок службы истек, все перегруженные варианты метода Unprotect выбросят исключение CryptographicException.

Предупреждение

Мы не советуем использовать эти API для защиты данных, которые должны храниться долгосрочно или бессрочно.

В примере выше используется не-DI код для создания экземпляра системы защиты данных. Чтобы запустить этот пример, сперва добавьте ссылку на пакет Microsoft.AspNet.DataProtection.Extensions.

 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
using System;
using System.IO;
using System.Threading;
using Microsoft.AspNetCore.DataProtection;
 
public class Program
{
    public static void Main(string[] args)
    {
        // create a protector for my application
 
        var provider = DataProtectionProvider.Create(new DirectoryInfo(@"c:\myapp-keys\"));
        var baseProtector = provider.CreateProtector("Contoso.TimeLimitedSample");
 
        // convert the normal protector into a time-limited protector
        var timeLimitedProtector = baseProtector.ToTimeLimitedDataProtector();
 
        // get some input and protect it for five seconds
        Console.Write("Enter input: ");
        string input = Console.ReadLine();
        string protectedData = timeLimitedProtector.Protect(input, lifetime: TimeSpan.FromSeconds(5));
        Console.WriteLine($"Protected data: {protectedData}");
 
        // unprotect it to demonstrate that round-tripping works properly
        string roundtripped = timeLimitedProtector.Unprotect(protectedData);
        Console.WriteLine($"Round-tripped data: {roundtripped}");
 
        // wait 6 seconds and perform another unprotect, demonstrating that the payload self-expires
        Console.WriteLine("Waiting 6 seconds...");
        Thread.Sleep(6000);
        timeLimitedProtector.Unprotect(protectedData);
    }
}
 
/*
 * SAMPLE OUTPUT
 *
 * Enter input: Hello!
 * Protected data: CfDJ8Hu5z0zwxn...nLk7Ok
 * Round-tripped data: Hello!
 * Waiting 6 seconds...
 * <<throws CryptographicException with message 'The payload expired at ...'>>

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