데이터 보호: 데이터 보호 API 시작하기

등록일시: 2017-03-29 08:00,  수정일시: 2017-05-18 04:14
조회수: 3,943
이 문서는 ASP.NET Core 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 ASP.NET Core 데이터 보호를 이용해서 데이터 보호 작업을 수행하는 가장 간단한 예제를 살펴봅니다.

가장 간단한 데이터 보호 작업은 다음과 같은 단계로 구성됩니다:

  1. 데이터 보호 공급자를 이용해서 데이터 보호자를 생성합니다.

  2. 보호할 데이터를 대상으로 Protect 메서드를 호출합니다.

  3. 평문으로 되돌릴 데이터를 대상으로 Unprotect 메서드를 호출합니다.

ASP.NET이나 SignalR 같은 대부분의 프레임워크들은 이미 내부적으로 데이터 보호 시스템을 구성해서 서비스 컨테이너에 추가해주고 있기 때문에, 개발자가 의존성 주입을 통해서 접근할 수 있습니다. 다음 예제는 의존성 주입을 위한 서비스 컨테이너의 구성 방법과 데이터 보호 스택을 등록하는 방법, DI를 통해서 데이터 보호 공급자를 가져오는 방법, 보호자를 생성하는 방법, 그리고 데이터를 보호했다가 다시 보호 해제하는 방법을 보여줍니다.

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

이 예제를 실행해보려면 새로운 콘솔 응용 프로그램 프로젝트를 생성한 다음, NuGet으로 Microsoft.AspNetCore.DataProtection 패키지와 Microsoft.Extensions.DependencyInjection 패키지를 설치하고 위의 코드를 작성하면 됩니다.

보호자를 생성할 때는 반드시 한 개 이상의 용도 문자열(Purpose Strings)을 제공해야 합니다. 용도 문자열은 소비자 간의 격리를 제공해주는 역할을 하는데, 가령 "green"이라는 용도 문자열을 이용해서 생성된 보호자는 "purple"이라는 용도 문자열을 이용해서 생성된 보호자에 의해서 만들어진 데이터의 보호를 해제하지 못합니다.

IDataProtectionProvider 인터페이스 및 IDataProtector 인터페이스의 인스턴스는 다중 호출자에 대해 스레드로부터 안전(Thread-Safe)합니다. 구성 요소에서 CreateProtector 메서드를 호출해서 IDataProtector 인터페이스 참조를 얻은 다음, 이 참조를 이용해서 Protect 메서드 및 Unprotect 메서드를 반복적으로 호출할 수 있도록 만들어졌습니다.

Unprotect 메서드 호출 시 보호된 페이로드를 검증하거나 판독하지 못하면 CryptographicException이 던져집니다. 일부 구성 요소에서는 보호 해제 작업 중 발생하는 예외를 무시해야 하는 경우도 있는데, 가령 인증 쿠키를 읽는 구성 요소는 요청 자체를 실패로 처리하는 대신 이 예외를 잡아서 처리함으로써 쿠키가 아예 존재하지 않는 것처럼 동작할 수 있습니다. 이런 동작이 필요한 구성 요소는 모든 예외를 감춰버리는 대신 명확하게 CryptographicException만 잡아야 합니다.