问题描述
我一直在使用 dotnet core 创建一个在 Linux 主机上的 Kubernetes 集群中运行的应用程序.在我测试时,它注意到在验证 CSRF 令牌时出现异常,这是有道理的,因为我还没有将机器密钥编辑为在每个实例上都相同.当我继续在 web.config 中设置机器密钥时,我注意到这在 .Net Core 中不再有效.
I have been using dotnet core to create an application that runs in a Kubernetes cluster on Linux hosts. As I was testing it noticed getting exceptions when validating the CSRF tokens, that makes sense since I did not edit the machine key to be the same on every instance yet. As i proceeded to set the machine key in web.config i noticed this would no longer work in .Net Core.
现在使用 DataProtection API 时,机器密钥不再有效.我尝试将 api 实现到我的应用程序中,但是当我阅读时,我需要使用网络共享来交换所有实例之间的密钥,我惊呆了.当然,必须有一种更简单(更好)的方法来实现这一点,而不必依赖共享来联机,对吗?
As is is now using the DataProtection API, the machine key no longer worked. I tried implementing the api into my application, but when i read i would need to use a network share to exchange the keys between all instances i was stunned. Surely there must be an easier (and better) way to accomplish this without having to rely on a share to be online right?
我尝试在 ConfigureServices 方法的 Startup 类中设置以下内容:
i tried to set the following in the Startup class in the ConfigureServices method:
services.AddDataProtection().SetApplicationName("DockerTestApplication");
我以某种方式希望使用应用程序名称生成密钥,但这并没有解决问题.
I somehow expected the keys to be generated using the applicationname, but this did not resolve the issue.
我发现了一些有趣的文档,它们都使用将不再编译的代码,我猜微软改变了一些东西:
I found some interesting docs that all use code that will no longer compile, i guess Microsoft changed up some things:
有没有人知道这个问题的解决方案,它也可以在 Linux 上运行,并且能够在实例之间通过网络共享令牌?
Does anyone know a solution to this problem that will also run on Linux and has the ability to share the tokens over the network between instances?
提前致谢!
推荐答案
我已经做了一些测试来支持我关于复制密钥的评论.首先,我使用以下代码创建了简单的控制台应用程序:
I've made some tests to back up my comment about copying keys. First I created simple console application with the following code:
var serviceCollection = new ServiceCollection();
serviceCollection.AddDataProtection()
.SetApplicationName("my-app")
.PersistKeysToFileSystem(new DirectoryInfo(@"G: mpsokeys"));
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 容器,使用特定的密钥文件夹在那里注册数据保护,解决和保护某些内容.
So, just create DI container, register data protection there with specific folder for keys, resolve and protect something.
这在目标文件夹中生成了以下密钥文件:
This generated the following key file in target folder:
<?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>
如您所见,文件相对简单.它说明了创建、激活、到期日期、使用的算法、对解串器类的引用,当然还有密钥本身.
As you see, file is relatively simple. It states creation, activation, expiration dates, algorithms used, reference to deserializer class and of course key itself.
现在我像这样配置了 asp.net 应用程序(所以,另一个应用程序,而不是那个控制台应用程序):
Now I configured asp.net application (so, another application, not that console one) like this:
services.AddDataProtection()
.SetApplicationName("my-app")
.PersistKeysToFileSystem(new DirectoryInfo(@"G: mpsokeys-asp"))
.DisableAutomaticKeyGeneration();
如果您现在尝试运行应用程序并执行一些需要保护的操作 - 它将失败,因为没有密钥并且自动密钥生成被禁用.但是,如果我将控制台应用程序生成的密钥复制到目标文件夹 - 它会愉快地使用它们.
If you now try to run application and do something that requires protection - it will fail, because there no keys and automatic key generation is disabled. However, if I copy keys generated by console app to the target folder - it willhappily use them.
因此,请注意复制密钥的常见安全问题、这些密钥的到期时间(可使用 SetDefaultKeyLifetime
配置)和 使用相同版本的 Microsoft.AspNetCore.DataProtection
在与您共享密钥的所有应用程序中(因为它的版本在密钥 xml 文件中指定) - 您应该没问题.最好在一个地方生成共享密钥,并在所有其他地方设置 DisableAutomaticKeyGeneration
.
So pay attention to the usual security concerns with copying keys, to expiration time of those keys (configurable with SetDefaultKeyLifetime
) and using the same version of Microsoft.AspNetCore.DataProtection
in all applications you share keys with (because it's version is specified in key xml file) - and you should be fine. It's better to generate your shared keys in one place and in all other places set DisableAutomaticKeyGeneration
.
这篇关于.Net Core Machine Key 替代 webfarm的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!