He estado usando dotnet core para crear una aplicación que se ejecuta en un clúster de Kubernetes en hosts Linux. Mientras lo probaba, noté que obtenía excepciones al validar los tokens CSRF, eso tiene sentido ya que todavía no edité la clave de la máquina para que sea la misma en todas las instancias. Cuando procedí a configurar la clave de la máquina en web.config, noté que esto ya no funcionaría en .Net Core.
Como ahora está usando la API de protección de datos, la clave de la máquina ya no funcionaba. Intenté implementar la API en mi aplicación, pero cuando leí, necesitaría usar un recurso compartido de red para intercambiar las claves entre todas las instancias, me sorprendió. Seguramente debe haber una manera más fácil (y mejor) de lograr esto sin tener que depender de un recurso compartido para estar en línea, ¿verdad?
Traté de configurar lo siguiente en la clase de inicio en el método ConfigureServices:
services.AddDataProtection().SetApplicationName("DockerTestApplication");
De alguna manera esperaba que las claves se generaran usando el nombre de la aplicación, pero esto no resolvió el problema.
Encontré algunos documentos interesantes que usan código que ya no se compilará, supongo que Microsoft cambió algunas cosas:
¿Alguien conoce una solución a este problema que también se ejecute en Linux y tenga la capacidad de compartir los tokens a través de la red entre instancias?
¡Gracias por adelantado!
Hice algunas pruebas para respaldar mi comentario sobre la copia de claves. Primero creé una aplicación de consola simple con el siguiente código:
var serviceCollection = new ServiceCollection(); serviceCollection.AddDataProtection() .SetApplicationName("my-app") .PersistKeysToFileSystem(new DirectoryInfo(@"G:\tmp\so\keys")); var services = serviceCollection.BuildServiceProvider(); var provider = services.GetService<IDataProtectionProvider>(); var protector = provider.CreateProtector("some_purpose"); Console.WriteLine(Convert.ToBase64String(protector.Protect(Encoding.UTF8.GetBytes("hello world"))));Entonces, simplemente cree un contenedor DI, registre la protección de datos allí con una carpeta específica para claves, resuelva y proteja algo.
Esto generó el siguiente archivo clave en la carpeta de destino:
<?xml version="1.0" encoding="utf-8"?> <key id="e6cbce11-9afd-43e6-94be-3f6057cb8a87" version="1"> <creationDate>2017-04-10T15:28:18.0565235Z</creationDate> <activationDate>2017-04-10T15:28:18.0144946Z</activationDate> <expirationDate>2017-07-09T15:28:18.0144946Z</expirationDate> <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60"> <descriptor> <encryption algorithm="AES_256_CBC" /> <validation algorithm="HMACSHA256" /> <masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection"> <!-- Warning: the key below is in an unencrypted form. --> <value>rVDib1M1BjbCqGctcP+N25zb+Xli9VWX46Y7+9tsoGywGnIg4p9K5QTM+c388i0mC0JBSLaFS2pZBRdR49hsLQ==</value> </masterKey> </descriptor> </descriptor> </key>Como ves, el archivo es relativamente simple. Indica la creación, la activación, las fechas de vencimiento, los algoritmos utilizados, la referencia a la clase de deserializador y, por supuesto, la clave en sí.
Ahora configuré la aplicación asp.net (otra aplicación, no la de la consola) así:
services.AddDataProtection() .SetApplicationName("my-app") .PersistKeysToFileSystem(new DirectoryInfo(@"G:\tmp\so\keys-asp")) .DisableAutomaticKeyGeneration();Si ahora intenta ejecutar la aplicación y hace algo que requiere protección, fallará, porque no hay claves y la generación automática de claves está deshabilitada. Sin embargo, si copio las claves generadas por la aplicación de la consola a la carpeta de destino, las usará felizmente.
Por lo tanto, preste atención a las preocupaciones de seguridad habituales con la copia de claves, el tiempo de vencimiento de esas claves (configurable con SetDefaultKeyLifetime ) y el uso de la misma versión de Microsoft.AspNetCore.DataProtection en todas las aplicaciones con las que comparte claves (porque su versión se especifica en key xml archivo) - y deberías estar bien. Es mejor generar sus claves compartidas en un lugar y en todos los demás lugares configure DisableAutomaticKeyGeneration .