问题:对于 Asp.Net Framework 4.x 和 Asp.Net Core 2 网站,如何使用存储在数据库中而不是文件系统或文件共享中的数据保护密钥来加密身份验证 cookie?
背景:我有一个 .Net Framework 4.x 网站和一个 .Net Core 2.0 网站。我需要在这两个应用程序之间共享身份验证 cookie 并使用 DataProtection 密钥加密数据。
在生产中,这些应用程序托管在多个 Web 服务器上。所以,我还需要在服务器之间共享密钥,因此也需要在数据库之间共享。目前,数据保护密钥在每台服务器上的文件系统位置之间手动同步。我想为每个 Web 服务器可以使用的数据保护密钥提供一个公共位置。显而易见的解决方案是文件共享,但这会给架构带来单点故障。
我宁愿使用支持这两个应用程序的通用数据库。我知道数据库本身就是一个 SPoF,但它已经是并且永远都是。
将其用于此目的不会增加风险。
我知道我可以创建自己的 IXmlRepository 实现来获取数据保护密钥并将其保存到我的数据库中。
我已经这样做了,而且效果很好。在调试期间,我可以看到应用程序在我的数据库中获取和设置数据保护密钥。
我在 StartUp.cs 中使用它,其中 DataProtectionRepository 是我对数据库的实现:
services.AddSingleton<IXmlRepository, DataProtectionRepository>();
var serviceProvider = services.BuildServiceProvider();
services.AddDataProtection().AddKeyManagementOptions(opt =>
opt.XmlRepository =
new DataProtectionRepository(serviceProvider.GetService<DataProtectionContext>()));
问题是当我设置 CookieAuthenticationOptions 时,TicketDataFormat 属性需要 IDataProtector 的实现来构造。IDataProtector 由 DataProtectionProvider.CreateProtector 提供,但要创建数据保护提供程序,需要 DirectoryInfo 对象来指示要存储密钥的位置。
var securityOptions =
services.BuildServiceProvider().GetService<IOptions<SecurityOptions>>();
var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(securityOptions.Value.KeyringLocation));
var dataProtector = protectionProvider.CreateProtector("CookieAuthenticationMiddleware", "Federation", "v2");
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
<blah>
options.TicketDataFormat = new TicketDataFormat(dataProtector);
<blah>
});
我想我可以创建自己的 IDataProtectionProvider 和 IDataProtector 实现,但这似乎很麻烦而且很危险,因为 IDataProtector 处理数据有效负载的实际保护和取消保护,但没有公开如何检索密钥或从何处获取密钥的任何细节. 另外,我真的不想更改任何实际的保护/取消保护功能。我只想从我的存储库中检索密钥。
我很难相信我在这个问题上是独一无二的。我完全走错了路吗?是否有替代解决方案,或者我应该只是放入文件共享并继续前进?
谢谢。