间歇性修改数据保护密钥集合导致 401 错误
Data Protection keys collection is intermittently modified causing 401 errors
我有两个共享身份验证 cookie 的站点:
- 生成 auth cookie 的主站点
- 托管 SignalR Hub 的聊天站点。
主站点的 cookie 通过并用于验证 SignalR 协商请求。
我最近部署了一些从 ASP.NET Framework 到 .NET5 的大规模更改。此更改的一部分意味着使用新的数据保护密钥,以便可以解密两个应用程序上的授权票证(以前,ASP.NET 框架版本只需要两个应用程序上的机器密钥匹配,这可以在 web.config).
这是数据保护代码的样子,用于主站点和聊天站点:
public void ConfigureServices(IServiceCollection services)
{
services.AddCustomDataProtection(_configuration);
...
}
public static IServiceCollection AddCustomDataProtection(this IServiceCollection services, IConfiguration configuration)
{
var siteSettings = configuration
.GetSection(SiteSettings.SectionName)
.Get<SiteSettings>();
var dataProtection = services.AddDataProtection()
.SetApplicationName(siteSettings.SiteName);
var dataProtectionSettings = configuration
.GetSection(DataProtectionSettings.SectionName)
.Get<DataProtectionSettings>();
if (!string.IsNullOrWhiteSpace(dataProtectionSettings.KeyVaultIdentifier))
{
dataProtection
.PersistKeysToAzureBlobStorage(
configuration.GetConnectionString("StorageConnectionString"),
dataProtectionSettings.KeyStoreContainerName,
dataProtectionSettings.KeyStoreBlobName)
.ProtectKeysWithAzureKeyVault(
new Uri(dataProtectionSettings.KeyVaultIdentifier),
new DefaultAzureCredential());
}
return services;
}
自部署以来,我们遇到了一些奇怪的问题,即存储在 Azure 存储中的数据保护密钥 blob 全天都在修改。发生这种情况似乎没有任何韵律或原因。
根据我的理解,数据保护密钥默认情况下每 90 天左右刷新一次,但是这种情况每天发生 1-2 次。应用程序中的代码从不直接与 Key Vault 密钥或数据保护密钥 blob 交互(仅通过下面发布的代码)并且我添加了显示正确设置的日志 are通过数据保护扩展方法。
另一方面,我一直遇到间歇性问题,当主站点向聊天站点发送协商请求时,它收到 401 错误,表明 cookie/auth 票证无效或其他原因无法解密。当通过重新启动主站点、注销然后再次登录来修改密钥时,我可以重现此问题。我认为这两个问题是相关的。
我对这种行为的暗中解释是,也许主站点正确地获取了数据保护密钥的更改,但聊天站点没有。然后,聊天站点无法解密使用它无权访问的密钥加密的授权票证。重新启动聊天站点可以解决问题,大概是因为数据保护密钥在启动时重新加载。
所以我主要担心两个问题:
- 为什么要修改数据保护密钥 blob?
- 如果确实有新密钥被添加到数据保护密钥集合中,为什么聊天站点不选择新密钥?
问题最终是主站点和聊天站点都将数据保护密钥存储在 Azure 存储中的同一个 blob 中。这导致了我在修改 blob 时看到的奇怪行为,进而导致了我遇到的应用程序错误。
我认为将密钥存储在同一位置会很好,因为我当时阅读了与 SetApplicationName() 方法相关的文档,导致密钥彼此隔离。不幸的是,这种隔离并没有扩展到实际的物理数据保护密钥,而是扩展到存储在其中的有效负载。 The documentation surrounding app isolation 已经更新,现在更加详细。
我有两个共享身份验证 cookie 的站点:
- 生成 auth cookie 的主站点
- 托管 SignalR Hub 的聊天站点。
主站点的 cookie 通过并用于验证 SignalR 协商请求。
我最近部署了一些从 ASP.NET Framework 到 .NET5 的大规模更改。此更改的一部分意味着使用新的数据保护密钥,以便可以解密两个应用程序上的授权票证(以前,ASP.NET 框架版本只需要两个应用程序上的机器密钥匹配,这可以在 web.config).
这是数据保护代码的样子,用于主站点和聊天站点:
public void ConfigureServices(IServiceCollection services)
{
services.AddCustomDataProtection(_configuration);
...
}
public static IServiceCollection AddCustomDataProtection(this IServiceCollection services, IConfiguration configuration)
{
var siteSettings = configuration
.GetSection(SiteSettings.SectionName)
.Get<SiteSettings>();
var dataProtection = services.AddDataProtection()
.SetApplicationName(siteSettings.SiteName);
var dataProtectionSettings = configuration
.GetSection(DataProtectionSettings.SectionName)
.Get<DataProtectionSettings>();
if (!string.IsNullOrWhiteSpace(dataProtectionSettings.KeyVaultIdentifier))
{
dataProtection
.PersistKeysToAzureBlobStorage(
configuration.GetConnectionString("StorageConnectionString"),
dataProtectionSettings.KeyStoreContainerName,
dataProtectionSettings.KeyStoreBlobName)
.ProtectKeysWithAzureKeyVault(
new Uri(dataProtectionSettings.KeyVaultIdentifier),
new DefaultAzureCredential());
}
return services;
}
自部署以来,我们遇到了一些奇怪的问题,即存储在 Azure 存储中的数据保护密钥 blob 全天都在修改。发生这种情况似乎没有任何韵律或原因。
根据我的理解,数据保护密钥默认情况下每 90 天左右刷新一次,但是这种情况每天发生 1-2 次。应用程序中的代码从不直接与 Key Vault 密钥或数据保护密钥 blob 交互(仅通过下面发布的代码)并且我添加了显示正确设置的日志 are通过数据保护扩展方法。
另一方面,我一直遇到间歇性问题,当主站点向聊天站点发送协商请求时,它收到 401 错误,表明 cookie/auth 票证无效或其他原因无法解密。当通过重新启动主站点、注销然后再次登录来修改密钥时,我可以重现此问题。我认为这两个问题是相关的。
我对这种行为的暗中解释是,也许主站点正确地获取了数据保护密钥的更改,但聊天站点没有。然后,聊天站点无法解密使用它无权访问的密钥加密的授权票证。重新启动聊天站点可以解决问题,大概是因为数据保护密钥在启动时重新加载。
所以我主要担心两个问题:
- 为什么要修改数据保护密钥 blob?
- 如果确实有新密钥被添加到数据保护密钥集合中,为什么聊天站点不选择新密钥?
问题最终是主站点和聊天站点都将数据保护密钥存储在 Azure 存储中的同一个 blob 中。这导致了我在修改 blob 时看到的奇怪行为,进而导致了我遇到的应用程序错误。
我认为将密钥存储在同一位置会很好,因为我当时阅读了与 SetApplicationName() 方法相关的文档,导致密钥彼此隔离。不幸的是,这种隔离并没有扩展到实际的物理数据保护密钥,而是扩展到存储在其中的有效负载。 The documentation surrounding app isolation 已经更新,现在更加详细。