Scenariusze bez obsługi wstrzykiwania zależności dla ochrony danych na platformie ASP.NET Core

Autor: Rick Anderson

System ASP.NET Core Data Protection jest zwykle dodawany do kontenera usługi i używany przez składniki zależne za pośrednictwem wstrzykiwania zależności (DI). Istnieją jednak przypadki, w których nie jest to możliwe lub pożądane, zwłaszcza w przypadku importowania systemu do istniejącej aplikacji.

Aby obsługiwać te scenariusze, pakiet Microsoft.AspNetCore.DataProtection.Extensions udostępnia konkretny typ , DataProtectionProviderktóry oferuje prosty sposób korzystania z ochrony danych bez polegania na di. Typ DataProtectionProvider implementuje IDataProtectionProviderelement . Konstruowanie DataProtectionProvider wymaga tylko podania DirectoryInfo wystąpienia, aby wskazać, gdzie powinny być przechowywane klucze kryptograficzne dostawcy, jak pokazano w poniższym przykładzie kodu:

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...
*/

Domyślnie DataProtectionProvider konkretny typ nie szyfruje nieprzetworzonego materiału klucza przed utrwalaniem go w systemie plików. Jest to obsługa scenariuszy, w których deweloper wskazuje udział sieciowy, a system ochrony danych nie może automatycznie deduować odpowiedniego mechanizmu szyfrowania klucza spoczynku.

DataProtectionProvider Ponadto konkretny typ domyślnie nie izoluje aplikacji. Wszystkie aplikacje korzystające z tego samego katalogu kluczy mogą współdzielić ładunki, o ile ich parametry przeznaczenia są zgodne.

Konstruktor DataProtectionProvider akceptuje opcjonalne wywołanie zwrotne konfiguracji, które może służyć do dostosowywania zachowań systemu. W poniższym przykładzie pokazano przywracanie izolacji za pomocą jawnego wywołania metody SetApplicationName. W przykładzie pokazano również, jak skonfigurować system do automatycznego szyfrowania utrwałych kluczy przy użyciu interfejsu DPAPI systemu Windows. Jeśli katalog wskazuje udział UNC, możesz chcieć rozpowszechnić udostępniony certyfikat na wszystkich odpowiednich maszynach i skonfigurować system do używania szyfrowania opartego na certyfikatach za pomocą wywołania metody 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();
    }
}

Napiwek

Wystąpienia konkretnego DataProtectionProvider typu są kosztowne do utworzenia. Jeśli aplikacja obsługuje wiele wystąpień tego typu i jeśli wszystkie używają tego samego katalogu magazynu kluczy, wydajność aplikacji może ulec pogorszeniu. Jeśli używasz DataProtectionProvider typu, zalecamy utworzenie tego typu raz i ponowne użycie go tak bardzo, jak to możliwe. Typ DataProtectionProvider i wszystkie IDataProtector wystąpienia utworzone na jego podstawie są bezpieczne wątkowo dla wielu wywołujących.