.Net Core Machine Key 替代 webfarm
.Net Core Machine Key alternative for webfarm
我一直在使用 dotnet core 创建 运行 在 Linux 主机上的 Kubernetes 集群中的应用程序。在我进行测试时,它注意到在验证 CSRF 令牌时出现异常,这是有道理的,因为我还没有将机器密钥编辑为在每个实例上都相同。当我继续在 web.config 中设置机器密钥时,我注意到这将不再适用于 .Net Core。
现在正在使用 DataProtection API,机器密钥不再有效。我尝试将 api 实现到我的应用程序中,但是当我阅读时,我需要使用网络共享在所有实例之间交换密钥,这让我大吃一惊。当然,必须有一种更简单(更好)的方法来完成此操作,而不必依赖在线共享,对吗?
我尝试在 ConfigureServices 方法的 Startup class 中设置以下内容:
services.AddDataProtection().SetApplicationName("DockerTestApplication");
我以某种方式期望使用应用程序名称生成密钥,但这并没有解决问题。
我发现了一些有趣的文档,它们都使用了不再编译的代码,我猜微软改变了一些东西:
有谁知道这个问题的解决方案,该解决方案也将 运行 Linux 并且能够在实例之间通过网络共享令牌?
提前致谢!
我做了一些测试来支持我关于复制密钥的评论。首先,我使用以下代码创建了简单的控制台应用程序:
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"))));
所以,只需创建 DI 容器,在其中使用特定的密钥文件夹注册数据保护,解决和保护一些东西。
这在目标文件夹中生成了以下密钥文件:
<?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>
如您所见,文件比较简单。它说明了创建、激活、到期日期、使用的算法、对反序列化器的引用 class,当然还有密钥本身。
现在我像这样配置 asp.net 应用程序(所以,另一个应用程序,而不是那个控制台应用程序):
services.AddDataProtection()
.SetApplicationName("my-app")
.PersistKeysToFileSystem(new DirectoryInfo(@"G:\tmp\so\keys-asp"))
.DisableAutomaticKeyGeneration();
如果您现在尝试 运行 应用程序并做一些需要保护的事情 - 它会失败,因为没有密钥并且自动密钥生成被禁用。但是,如果我将控制台应用程序生成的密钥复制到目标文件夹 - 它会
愉快地使用它们。
因此请注意复制密钥时常见的安全问题,这些密钥的过期时间(可使用 SetDefaultKeyLifetime
配置)和 使用相同版本的 Microsoft.AspNetCore.DataProtection
在你共享密钥的所有应用程序中(因为它的版本在密钥 xml 文件中指定) - 你应该没问题。最好在一个地方生成共享密钥,然后在所有其他地方设置 DisableAutomaticKeyGeneration
.
我一直在使用 dotnet core 创建 运行 在 Linux 主机上的 Kubernetes 集群中的应用程序。在我进行测试时,它注意到在验证 CSRF 令牌时出现异常,这是有道理的,因为我还没有将机器密钥编辑为在每个实例上都相同。当我继续在 web.config 中设置机器密钥时,我注意到这将不再适用于 .Net Core。
现在正在使用 DataProtection API,机器密钥不再有效。我尝试将 api 实现到我的应用程序中,但是当我阅读时,我需要使用网络共享在所有实例之间交换密钥,这让我大吃一惊。当然,必须有一种更简单(更好)的方法来完成此操作,而不必依赖在线共享,对吗?
我尝试在 ConfigureServices 方法的 Startup class 中设置以下内容:
services.AddDataProtection().SetApplicationName("DockerTestApplication");
我以某种方式期望使用应用程序名称生成密钥,但这并没有解决问题。
我发现了一些有趣的文档,它们都使用了不再编译的代码,我猜微软改变了一些东西:
有谁知道这个问题的解决方案,该解决方案也将 运行 Linux 并且能够在实例之间通过网络共享令牌?
提前致谢!
我做了一些测试来支持我关于复制密钥的评论。首先,我使用以下代码创建了简单的控制台应用程序:
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"))));
所以,只需创建 DI 容器,在其中使用特定的密钥文件夹注册数据保护,解决和保护一些东西。
这在目标文件夹中生成了以下密钥文件:
<?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>
如您所见,文件比较简单。它说明了创建、激活、到期日期、使用的算法、对反序列化器的引用 class,当然还有密钥本身。
现在我像这样配置 asp.net 应用程序(所以,另一个应用程序,而不是那个控制台应用程序):
services.AddDataProtection()
.SetApplicationName("my-app")
.PersistKeysToFileSystem(new DirectoryInfo(@"G:\tmp\so\keys-asp"))
.DisableAutomaticKeyGeneration();
如果您现在尝试 运行 应用程序并做一些需要保护的事情 - 它会失败,因为没有密钥并且自动密钥生成被禁用。但是,如果我将控制台应用程序生成的密钥复制到目标文件夹 - 它会 愉快地使用它们。
因此请注意复制密钥时常见的安全问题,这些密钥的过期时间(可使用 SetDefaultKeyLifetime
配置)和 使用相同版本的 Microsoft.AspNetCore.DataProtection
在你共享密钥的所有应用程序中(因为它的版本在密钥 xml 文件中指定) - 你应该没问题。最好在一个地方生成共享密钥,然后在所有其他地方设置 DisableAutomaticKeyGeneration
.