ASP.NET Core에서 보호된 페이로드의 수명 제한

애플리케이션 개발자가 설정된 시간 후에 만료되는 보호된 페이로드를 만들려고 하는 시나리오가 있습니다. 예를 들어 보호된 페이로드는 1시간 동안만 유효해야 하는 암호 재설정 토큰을 나타낼 수 있습니다. 개발자는 포함된 만료 날짜가 포함된 자체 페이로드 형식을 만들 수 있으며, 고급 개발자는 이 작업을 수행할 수 있지만 이러한 만료를 관리하는 대부분의 개발자는 지루한 작업을 수행할 수 있습니다.

개발자 대상이 더 쉽게 사용할 수 있도록 Microsoft.AspNetCore.DataProtection.Extensions 패키지에는 설정된 시간 후 자동으로 만료되는 페이로드를 만들기 위한 유틸리티 API가 포함되어 있습니다. 이러한 API는 ITimeLimitedDataProtector 인터페이스를 구현합니다.

API 사용량

ITimeLimitedDataProtector 인터페이스는 시간 제한/자체 만료 페이로드를 보호하고 보호 해제하는 핵심 인터페이스입니다. ITimeLimitedDataProtector 인스턴스를 만들려면 먼저 특정 용도를 사용하여 생성된 일반 IDataProtector 인스턴스가 필요합니다. IDataProtector 인스턴스를 사용할 수 있게 되면 IDataProtector.ToTimeLimitedDataProtector 확장 메서드를 호출하여 기본 제공 만료 기능이 포함된 보호기를 다시 가져옵니다.

ITimeLimitedDataProtector는 다음과 같은 API 노출 및 확장 메서드를 노출합니다.

  • CreateProtector(문자열 용도): ITimeLimitedDataProtector - 이 API는 루트 시간 제한 보호기에서 용도 체인을 만드는 데 사용할 수 있다는 점에서 기존 IDataProtectionProvider.CreateProtector와 비슷합니다.

  • Protect(바이트[] 일반 텍스트, DateTimeOffset 만료) : 바이트[]

  • Protect(바이트[] 일반 텍스트, TimeSpan 수명) : 바이트[]

  • Protect(바이트[] 일반 텍스트) : 바이트[]

  • Protect(문자열 일반 텍스트, DateTimeOffset 만료): 문자열

  • Protect(문자열 일반 텍스, TimeSpan 수명) : 문자열

  • Protect(일반 텍스트 문자열): 문자열

일반 텍스트를 사용하는 핵심 Protect 방법 외에 페이로드의 만료 날짜를 지정할 수 있는 새로운 오버로드가 있습니다. 만료 날짜는 절대 날짜(DateTimeOffset을 통해) 또는 상대 시간(TimeSpan을 통해 현재 시스템 시간에서)으로 지정할 수 있습니다. 만료를 사용하지 않는 오버로드를 호출하면 페이로드가 만료되지 않는다고 가정합니다.

  • Unprotect(바이트[] protectedData, out DateTimeOffset 만료) : 바이트[]

  • Unprotect(바이트[] protectedData) : 바이트[]

  • Unprotect(문자열 protectedData, out DateTimeOffset 만료) : 문자열

  • Unprotect(문자열 protectedData) : 문자열

Unprotect 메서드는 보호되지 않는 원래 데이터를 반환합니다. 페이로드가 아직 만료되지 않은 경우 절대 만료는 원래의 보호되지 않는 데이터와 함께 선택적 out 매개 변수로 반환됩니다. 페이로드가 만료된 경우 Unprotect 메서드의 모든 오버로드가 CryptographicException을 throw합니다.

Warning

이러한 API를 사용하여 장기 또는 무한 지속성을 필요로 하는 페이로드를 보호하는 것은 권장되지 않습니다. "한 달 후에 영구적으로 복구가 불가능하도록 보호된 페이로드를 감당할 수 있을까요?"라고 질문하는 것이 경험상 좋을 수 있습니다. 대답이 아니요인 경우 개발자는 대체 API를 고려해야 합니다.

아래 샘플에서는 데이터 보호 시스템을 인스턴스화하기 위해 DI 이외의 코드 경로를 사용합니다. 이 샘플을 실행하려면 먼저 Microsoft.AspNetCore.DataProtection.Extensions 패키지에 대한 참조를 추가했는지 확인합니다.

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 ...'>>

 */