Cenários sem reconhecimento de DI para Proteção de Dados no ASP.NET Core
Por Rick Anderson
O sistema ASP.NET Core Data Protection é normalmente adicionado a um contêiner de serviço e consumido por componentes dependentes por meio de injeção de dependência (DI). No entanto, há casos em que isso não é viável ou desejado, especialmente ao importar o sistema para um aplicativo existente.
Para dar suporte a esses cenários, o pacote DataProtectionProvider
implementa IDataProtectionProvider. A construção de DataProtectionProvider
requer apenas o fornecimento de uma instância DirectoryInfo para indicar onde as chaves criptográficas do provedor devem ser armazenadas, como visto no exemplo de código a seguir:
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...
*/
Por padrão, o tipo concreto DataProtectionProvider
não criptografa o material da chave em bruto antes de armazená-lo no sistema de arquivos. Isso é para suportar cenários em que o desenvolvedor aponta para um compartilhamento de rede e o sistema de Proteção de Dados não pode deduzir automaticamente um mecanismo de criptografia de chave em repouso apropriado.
Além disso, o tipo concreto DataProtectionProvider
não isolar aplicativos por padrão. Todos os aplicativos que usam o mesmo diretório de chave podem compartilhar cargas úteis, desde que seus parâmetros de finalidade correspondam.
O construtor DataProtectionProvider aceita uma função de retorno de configuração opcional que pode ser usada para ajustar o comportamento do sistema. O exemplo abaixo demonstra a restauração do isolamento com uma chamada explícita para SetApplicationName. O exemplo também demonstra a configuração do sistema para criptografar automaticamente chaves persistentes usando DPAPI do Windows. Se o diretório apontar para um compartilhamento UNC, talvez você queira distribuir um certificado compartilhado em todas as máquinas relevantes e configurar o sistema para usar criptografia baseada em certificado com uma chamada para 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();
}
}
Dica
Instâncias do tipo concreto DataProtectionProvider
são caras de criar. Se um aplicativo mantiver várias instâncias desse tipo e se todas estiverem usando o mesmo diretório de armazenamento de chaves, o desempenho do aplicativo poderá se degradar. Se você usar o tipo DataProtectionProvider
, recomendamos que você crie esse tipo uma vez e o reutilize o máximo possível. O tipo DataProtectionProvider
e todas as instâncias IDataProtector criadas a partir desse tipo são seguras para uso com múltiplos chamadores.