ASP.NET core 2.2 web api 记录与数据保护密钥相关的警告:我们应该如何处理这个问题?

ASP.NET core 2.2 web api logs warnings related to data protection keys: how should we handle this issue?

我们有一个 ASP.NET 核心 2.2 网络应用程序公开了一些网络 api 控制器。 我们的应用程序没有任何类型的身份验证机制,所有公开的端点都可以由匿名用户调用。

当我们在 IIS 下托管应用程序时,我们会在应用程序启动时收到三个奇怪的警告消息。这些是我们得到的日志:

  1. 使用内存存储库。密钥不会持久存储。
  2. 用户配置文件和 HKLM 注册表均不可用。使用临时密钥存储库。应用程序退出时,受保护的数据将不可用。
  3. 未配置 XML 加密器。密钥 {GUID} 可能会以未加密的形式保存到存储中。

所有这些日志都有 Microsoft.AspNetCore.DataProtection 作为日志上下文,并且由 ASP.NET 核心框架内部编写。

这些日志的含义对我来说似乎很清楚:有一个 "key"(不管它是什么意思)将被保存在内存中,因为没有提供注册表存储(当然,它将在应用程序退出时丢失)。还有一条警告表明,如果保留此密钥,将不会以任何方式加密。

此时我会提出以下问题:

一些附加信息:

一些在线博客建议此类数据保护警告与 ASP.NET 身份的使用有关,但我们不在我们的应用程序中使用身份(我们没有启用身份验证)。其他博客建议设置托管应用程序池以加载用户配置文件:我已经尝试过,但警告仍然存在。

2019 年 4 月 2 日重要更新

感谢 asp.net 核心开发团队的帮助,我解决了这个问题。 如需完整参考,请参阅 the github issue I opened yesterday

简而言之,问题与我的开发机器上的 IIS 配置有关。为了使 ASP.NET 核心数据保护按预期工作,有一些针对 IIS 和托管应用程序池的特定配置 (see here for a complete reference)

2019 年 9 月 13 日更新

对于那些在 ASP.NET 核心 2.2 网络应用程序中有相同警告的人,我建议看一下这个 github issue

我们现在已经在我们的产品中添加了cookie认证,我们需要支持kubernetes托管。在使用 cookie 身份验证的 kubernetes 中,此 Whosebug 问题中讨论的警告是相关的,因为您必须为 ASP.NET 核心提供一个存储 ASP.NET 核心数据保护系统所需密钥的位置。

我们选择在 MongoDB 中实施持久密钥环。通过删除 Id 属性 可以找到一些细节 here. I can't show the code here (the project is not open source), but we have basically started from the official entity framework core key ring store and substituted all the usages of entity framework db context with an injected IMongoCollection<DataProtectionKey>. We have also modified the DataProtectionKey class(我们更喜欢让 MongoDB 生成自己的对象 ID)。

各种组件使用数据保护在运行时加密数据,例如:

  • 身份验证 cookie
  • 身份密码重置令牌

您可以在文档中阅读更多相关信息:https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/introduction

您对警告的理解正确,它已经创建了一个密钥,但无法决定将密钥存储在何处。 因此,如果应用程序重新启动,它将丢失。 如果你不使用例如身份验证 cookie,您可以忽略这些警告。 您还可以在应用程序文件夹之外配置存储位置。

如果您没有使用任何身份验证机制(例如:ASP.NET 使用此类密钥的核心身份)并且您没有在其他地方使用 DataProtection API很高兴(现在)。

那里发生了什么?

您进入了用于存储密钥的回退机制(在内存中)。当您的应用重新启动时,您将丢失您的密钥。

你会遇到什么问题?

示例:如果您使用身份验证机制,您最终会得到搞砸的身份验证 cookie、电子邮件验证令牌、重置密码令牌等

你现在可以做什么?

如果你想要(面向未来的解决方案),你可以将密钥存储在某个地方(例如:Redis)。

进一步阅读:https://cypressnorth.com/programming/solved-using-memory-repository-keys-will-not-persisted-storage-asp-net-core-iis/

ASP.Net 核心 DataProtection 将密钥存储在 HOME 目录 (/root/.aspnet/DataProtection-Keys) 中,因此当容器重新启动密钥丢失时,这可能会导致服务崩溃。

这可以通过在

处保留密钥来解决
  • 在持久位置(卷)保留密钥并安装该卷 到 docker 容器
  • 在 Azure 或 Redis 等外部密钥存储中保留密钥

有关 ASP.NET 数据保护的更多详细信息:

https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-3.1

https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-3.1

使用以下命令将外部卷 (C:/temp-kyes) 挂载到 docker 容器卷 (/root/.aspnet/DataProtection-Keys)

docker run -d -v /c/temp-keys:/root/.aspnet/DataProtection-Keys container-name

此外,您需要更新 Starup.cs - ConfigureServices 以配置 DataProtection 策略

services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(@"C:\temp-keys\"))
                .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration()
                {
                    EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
                    ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
                });