ASP.NET Core 데이터 보호에 대한 비-DI 인식 시나리오

작성자: Rick Anderson

ASP.NET Core 데이터 보호 시스템은 일반적으로 서비스 컨테이너에 추가되며 DI(종속성 주입)를 통해 종속성 구성 요소에서 사용됩니다. 그러나 특히 시스템을 기존 앱으로 가져올 때 이것이 가능하지 않거나 바람직하지 않은 경우가 있습니다.

이러한 시나리오를 지원하기 위해 Microsoft.AspNetCore.DataProtection.Extensions 패키지는 DI를 사용하지 않고 데이터 보호를 사용하는 간단한 방법을 제공하는 구체적인 형식 DataProtectionProvider을 제공합니다. DataProtectionProvider 형식으로 IDataProtectionProvider를 구현할 수 있습니다. DataProtectionProvider 생성하려면 다음 코드 샘플과 같이 공급자의 암호화 키를 저장해야 하는 위치를 나타내는 인스턴스만 제공해야 DirectoryInfo 합니다.

using System;
using System.IO;
using Microsoft.AspNetCore.DataProtection;

public class Program
{
    public static void Main(string[] args)
    {
        // Get the path to %LOCALAPPDATA%\myapp-keys
        var destFolder = Path.Combine(
            System.Environment.GetEnvironmentVariable("LOCALAPPDATA"),
            "myapp-keys");

        // Instantiate the data protection system at this folder
        var dataProtectionProvider = DataProtectionProvider.Create(
            new DirectoryInfo(destFolder));

        var protector = dataProtectionProvider.CreateProtector("Program.No-DI");
        Console.Write("Enter input: ");
        var input = Console.ReadLine();

        // Protect the payload
        var protectedPayload = protector.Protect(input);
        Console.WriteLine($"Protect returned: {protectedPayload}");

        // Unprotect the payload
        var unprotectedPayload = protector.Unprotect(protectedPayload);
        Console.WriteLine($"Unprotect returned: {unprotectedPayload}");

        Console.WriteLine();
        Console.WriteLine("Press any key...");
        Console.ReadKey();
    }
}

/*
 * SAMPLE OUTPUT
 *
 * Enter input: Hello world!
 * Protect returned: CfDJ8FWbAn6...ch3hAPm1NJA
 * Unprotect returned: Hello world!
 *
 * Press any key...
*/

기본적으로 DataProtectionProvider 구체적인 형식은 원시 키 자료를 파일 시스템에 유지하기 전에 암호화하지 않습니다. 이는 개발자가 네트워크 공유를 가리키고 데이터 보호 시스템이 적절한 미사용 키 암호화 메커니즘을 자동으로 추론할 수 없는 시나리오를 지원하기 위한 것입니다.

또한 DataProtectionProvider 구체적인 형식은 기본적으로 앱을 격리하지 않습니다. 동일한 키 디렉터리를 사용하는 모든 앱은 용도 매개 변수가 일치하는 한 페이로드를 공유할 수 있습니다.

DataProtectionProvider 생성자는 시스템의 동작을 조정하는 데 사용할 수 있는 선택적 구성 콜백을 허용합니다. 아래 샘플에서는 명시적 호출을 사용하여 격리를 복원하는 방법을 SetApplicationName보여 줍니다. 또한 이 샘플에서는 Windows DPAPI를 사용하여 지속형 키를 자동으로 암호화하도록 시스템을 구성하는 방법도 설명합니다. 디렉터리가 UNC 공유를 가리키는 경우 모든 관련 컴퓨터에 공유 인증서를 배포하고 호출 ProtectKeysWithCertificate과 함께 인증서 기반 암호화를 사용하도록 시스템을 구성할 수 있습니다.

using System;
using System.IO;
using Microsoft.AspNetCore.DataProtection;

public class Program
{
    public static void Main(string[] args)
    {
        // Get the path to %LOCALAPPDATA%\myapp-keys
        var destFolder = Path.Combine(
            System.Environment.GetEnvironmentVariable("LOCALAPPDATA"),
            "myapp-keys");

        // Instantiate the data protection system at this folder
        var dataProtectionProvider = DataProtectionProvider.Create(
            new DirectoryInfo(destFolder),
            configuration =>
            {
                configuration.SetApplicationName("my app name");
                configuration.ProtectKeysWithDpapi();
            });

        var protector = dataProtectionProvider.CreateProtector("Program.No-DI");
        Console.Write("Enter input: ");
        var input = Console.ReadLine();

        // Protect the payload
        var protectedPayload = protector.Protect(input);
        Console.WriteLine($"Protect returned: {protectedPayload}");

        // Unprotect the payload
        var unprotectedPayload = protector.Unprotect(protectedPayload);
        Console.WriteLine($"Unprotect returned: {unprotectedPayload}");

        Console.WriteLine();
        Console.WriteLine("Press any key...");
        Console.ReadKey();
    }
}

DataProtectionProvider 구체적인 형식의 인스턴스는 만드는 데 비용이 많이 듭니다. 앱이 이 유형의 여러 인스턴스를 유지 관리하고 모두 동일한 키 스토리지 디렉터리를 사용하는 경우 앱 성능이 저하될 수 있습니다. DataProtectionProvider 형식을 사용하는 경우 이 형식을 한 번 만들고 가능한 한 많이 다시 사용하는 것이 좋습니다. 형식 및 이 DataProtectionProvider 형식에서 만든 모든 IDataProtector 인스턴스는 여러 호출자에게 스레드로부터 안전합니다.