Proveedores de almacenamiento de claves en ASP.NET Core
El sistema de protección de datos emplea un mecanismo de detección de forma predeterminada para determinar dónde se deben conservar las claves criptográficas. El desarrollador puede invalidar el mecanismo de detección predeterminado y especificar manualmente la ubicación.
Advertencia
Si especificas una ubicación de persistencia de clave explícita, el sistema de protección de datos anula el registro del cifrado de claves predeterminado en rest, por lo que las claves ya no se cifran en rest. Se recomienda especificar además un mecanismo de cifrado de clave explícito para las implementaciones de producción.
Sistema de archivos
Para configurar un repositorio de claves basado en el sistema de archivos, llame a la rutina de configuración de PersistKeysToFileSystem como se muestra a continuación. Proporcione un DirectoryInfo que apunte al repositorio donde se deben almacenar las claves:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys\"));
}
DirectoryInfo
puede apuntar a un directorio en el equipo local o a una carpeta de un recurso compartido de red. Si apuntas a un directorio en el equipo local (y el escenario es que solo las aplicaciones de la máquina local requieren acceso para usar este repositorio), considera la posibilidad de usar Windows DPAPI (en Windows) para cifrar las claves en rest. De lo contrario, considera la posibilidad de usar un certificado X.509 para cifrar las claves en rest.
Azure Storage
El paquete Azure.Extensions.AspNetCore.DataProtection.Blobs permite almacenar claves de protección de datos en Azure Blob Storage. Las claves se pueden compartir entre varias instancias de una aplicación web. Las aplicaciones pueden compartir cookies de autenticación o protección CSRF entre varios servidores.
Para configurar el proveedor de Azure Blob Storage, llame a una de las sobrecargas de PersistKeysToAzureBlobStorage.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("<blob URI including SAS token>"));
}
Si la aplicación web se ejecuta como un servicio de Azure, se puede usar la cadena de conexión para autenticarse en Azure Storage mediante Azure.Storage.Blobs.
Advertencia
En este artículo se muestra el uso de cadena de conexión. Con una base de datos local, el usuario no tiene que autenticarse, pero en producción, cadena de conexión a veces incluye una contraseña para autenticarse. Una credencial de contraseña de propietario de recursos (ROPC) es un riesgo de seguridad que se debe evitar en las bases de datos de producción. Las aplicaciones de producción deben usar el flujo de autenticación más seguro disponible. Para obtener más información sobre la autenticación de aplicaciones implementadas para probar o entornos de producción, consulte Flujos de autenticación seguros.
string connectionString = "<connection_string>";
string containerName = "my-key-container";
string blobName = "keys.xml";
BlobContainerClient container = new BlobContainerClient(connectionString, containerName);
// optional - provision the container automatically
await container.CreateIfNotExistsAsync();
BlobClient blobClient = container.GetBlobClient(blobName);
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(blobClient);
Nota:
La cadena de conexión a la cuenta de almacenamiento se puede encontrar en Azure Portal en la sección "Claves de acceso" o mediante la ejecución del siguiente comando de la CLI:
az storage account show-connection-string --name <account_name> --resource-group <resource_group>
Redis
El paquete Microsoft.AspNetCore.DataProtection.StackExchangeRedis permite almacenar claves de protección de datos en una caché de Redis. Las claves se pueden compartir entre varias instancias de una aplicación web. Las aplicaciones pueden compartir cookies de autenticación o protección CSRF entre varios servidores.
El paquete Microsoft.AspNetCore.DataProtection.Redis permite almacenar claves de protección de datos en una caché de Redis. Las claves se pueden compartir entre varias instancias de una aplicación web. Las aplicaciones pueden compartir cookies de autenticación o protección CSRF entre varios servidores.
Para configurar en Redis, llame a una de las sobrecargas de PersistKeysToStackExchangeRedis:
public void ConfigureServices(IServiceCollection services)
{
var redis = ConnectionMultiplexer.Connect("<URI>");
services.AddDataProtection()
.PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
}
Para configurar en Redis, llame a una de las sobrecargas de PersistKeysToRedis:
public void ConfigureServices(IServiceCollection services)
{
var redis = ConnectionMultiplexer.Connect("<URI>");
services.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys");
}
Para obtener más información, vea los temas siguientes:
- StackExchange.Redis ConnectionMultiplexer
- Azure Redis Cache
- Ejemplos de DataProtection de ASP.NET Core
Registro
Solo se aplica a las implementaciones de Windows.
A veces, es posible que la aplicación no tenga acceso de escritura al sistema de archivos. Considera un escenario en el que una aplicación se ejecuta como una cuenta de servicio virtual (como el objeto identity del grupo de aplicaciones de w3wp.exe). En estos casos, el administrador puede aprovisionar una clave del Registro a la que pueda acceder la identity de la cuenta de servicio. Llame al método de extensión PersistKeysToRegistry como se muestra a continuación. Proporcione un RegistryKey que apunte a la ubicación donde se deben almacenar las claves criptográficas:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Sample\keys", true));
}
Importante
Se recomienda usar Windows DPAPI para cifrar las claves en rest.
Entity Framework Core
El paquete Microsoft.AspNetCore.DataProtection.EntityFrameworkCore proporciona un mecanismo para almacenar claves de protección de datos en una base de datos mediante Entity Framework Core. El paquete NuGet de Microsoft.AspNetCore.DataProtection.EntityFrameworkCore
debe agregarse al archivo del proyecto, no forma parte del metapaquete de Microsoft.AspNetCore.App.
Con este paquete, las claves se pueden compartir entre varias instancias de una aplicación web.
Para configurar el proveedor de EF Core, llame al método PersistKeysToDbContext:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
// Add a DbContext to store your Database Keys
services.AddDbContext<MyKeysContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyKeysConnection")));
// using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.PersistKeysToDbContext<MyKeysContext>();
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Si quiere que los comentarios de código se traduzcan en más idiomas además del inglés, háganoslo saber en este problema de debate de GitHub.
El parámetro genérico, TContext
, debe heredar de DbContext e implementar IDataProtectionKeyContext:
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;
namespace WebApp1
{
class MyKeysContext : DbContext, IDataProtectionKeyContext
{
// A recommended constructor overload when using EF Core
// with dependency injection.
public MyKeysContext(DbContextOptions<MyKeysContext> options)
: base(options) { }
// This maps to the table that stores keys.
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
}
Cree la tabla DataProtectionKeys
.
Ejecute los siguientes comandos en la ventana consola del administrador de paquetes (PMC):
Add-Migration AddDataProtectionKeys -Context MyKeysContext
Update-Database -Context MyKeysContext
MyKeysContext
es el DbContext
definido en el ejemplo de código anterior. Si usa un DbContext
con un nombre diferente, sustituya el nombre DbContext
por MyKeysContext
.
La entidad o clase de DataProtectionKeys
adopta la estructura que se muestra en la tabla siguiente.
Propiedad o campo | Tipo CLR | Tipo de SQL |
---|---|---|
Id |
int |
int , PK, IDENTITY(1,1) , no es null |
FriendlyName |
string |
nvarchar(MAX) , null |
Xml |
string |
nvarchar(MAX) , null |
Repositorio de claves personalizado
Si los mecanismos de la bandeja de entrada no son apropiados, el desarrollador puede especificar su propio mecanismo de persistencia de claves proporcionando un IXmlRepository personalizado.