Niet-DI-bewuste scenario's voor gegevensbescherming in ASP.NET Core
Door Rick Anderson
Het ASP.NET Core Data Protection-systeem wordt normaal gesproken toegevoegd aan een servicecontainer en wordt gebruikt door afhankelijke onderdelen via afhankelijkheidsinjectie (DI). Er zijn echter gevallen waarin dit niet haalbaar of gewenst is, met name bij het importeren van het systeem in een bestaande app.
Ter ondersteuning van deze scenario's biedt het Microsoft.AspNetCore.DataProtection.Extensions-pakket een concreet type, DataProtectionProvider, dat een eenvoudige manier biedt om Gegevensbeveiliging te gebruiken zonder gebruik te maken van DI. Het type DataProtectionProvider
implementeert IDataProtectionProvider. Voor het samenstellen van DataProtectionProvider
is alleen een DirectoryInfo exemplaar vereist om aan te geven waar de cryptografische sleutels van de provider moeten worden opgeslagen, zoals te zien is in het volgende codevoorbeeld:
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...
*/
Standaard versleutelt het DataProtectionProvider
concrete-type het onbewerkte sleutelmateriaal niet voordat het naar het bestandssysteem wordt bewaard. Dit is bedoeld ter ondersteuning van scenario's waarbij de ontwikkelaar verwijst naar een netwerkshare en het gegevensbeschermingssysteem niet automatisch een geschikt versleutelingsmechanisme voor sleutels in rust kan afleiden.
Bovendien het DataProtectionProvider
concrete type apps niet standaard isoleren. Alle apps die dezelfde sleutelmap gebruiken, kunnen nettoladingen delen zolang hun doelparameters overeenkomen.
De DataProtectionProvider constructor accepteert een optionele callback van configuraties die kan worden gebruikt om het gedrag van het systeem aan te passen. In het onderstaande voorbeeld ziet u hoe isolatie wordt hersteld met een expliciete aanroep naar SetApplicationName. In het voorbeeld ziet u ook hoe u het systeem configureert voor het automatisch versleutelen van persistente sleutels met behulp van Windows DPAPI. Als de map verwijst naar een UNC-share, kunt u een gedeeld certificaat distribueren over alle relevante computers en het systeem configureren voor het gebruik van versleuteling op basis van certificaten met een aanroep naar 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();
}
}
Tip
Exemplaren van het DataProtectionProvider
betontype zijn duur om te maken. Als een app meerdere exemplaren van dit type onderhoudt en als ze allemaal dezelfde sleutelopslagmap gebruiken, kunnen de prestaties van de app afnemen. Als u het type DataProtectionProvider
gebruikt, raden we u aan dit type eenmaal te maken en zo veel mogelijk opnieuw te gebruiken. Het DataProtectionProvider
type en alle IDataProtector exemplaren die ermee zijn gemaakt, zijn thread-veilig voor meerdere bellers.