Web场上的ASP.NET Core数据保护

时间:2019-05-24 16:46:24

标签: asp.net-core web-farm data-protection

我有一个使用Cookie身份验证并在Web场上运行的ASP.NET Core应用程序。数据保护密钥存储在DB中。我的应用程序实现了IXmlRepository,而ASP.NET Core将调用IXmlRepository.GetAllElements来获取密钥环。因此,所有节点中的应用程序都使用相同的密钥环,并且可以在Node2中解密在Node1中加密的cookie。很好。

但是,数据保护密钥将过期,并且ASP.NET Core将生成一个新密钥。 ASP.NET Core还会缓存密钥,并将每18-24小时刷新一次。因此,当密钥过期时,Node1可能会生成一个新密钥,但是所有其他节点可能不会立即刷新并获取新密钥。由Node1加密的Cookie无法在所有其他节点上解密。

ASP.NET Core如何处理这种情况?

我读了这个https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/web-farm?view=aspnetcore-2.2,上面写着

  

默认配置通常不适用于在Web场中托管应用程序。实现共享密钥环的另一种方法是始终将用户请求路由到同一节点。

使用用户节点登录后,将所有请求路由到同一节点是唯一的选择吗?

2 个答案:

答案 0 :(得分:1)

这里有一个有趣的GitHub问题,在这里讨论了钥匙圈的存储和钥匙的旋转 https://github.com/dotnet/aspnetcore/issues/26786

此外,如果您想进一步了解如何将密钥环存储在Azure Key Vault中,那么我最近在这里博客了一下: Storing the ASP.NET Core Data Protection Key Ring in Azure Key Vault

答案 1 :(得分:0)

原则上,这与任何其他共享配置方案没有什么不同。您需要做两件事:

  1. 将密钥环保留到所有进程/应用程序可以访问的公用文件系统或网络位置路径:

    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
    
  2. 确保所有进程/应用程序都使用相同的应用程序名称:

    services.AddDataProtection()
        .SetApplicationName("shared app name");
    

第二项对于Web场方案而言不太重要,因为它都是相同的应用程序,并且默认情况下具有相同的应用程序名称。但是,最好明确一些,然后,如果您确实需要与一个完全不同的应用程序共享,那么您已经设置好并可以使用了。

简而言之,您需要添加以下代码:

services.AddDataProtection()
    .SetApplicationName("shared app name")
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));

@LGSon在您的问题下方的评论中指出,最终您还会遇到缓存/会话的问题。无论是相同的“应用程序”,您都应将Web场中的每个实例视为一个单独的应用程序。每个进程都是一个单独的进程,这意味着它们具有自己的单独的内存分配。如果您使用内存缓存(这也是会话的默认存储),那么该缓存将仅对创建它的单个进程可用。因此,每个进程将以单独的缓存和单独的会话结束。要共享此信息,您需要使用分布式缓存(例如Redis或SQL Server)。参见:https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.2#establish-distributed-caching-services

注意:即使有一个“分布式”内存缓存,它实际上并不是分布式的。这只是存储在内存中的IDistributedCache的一种实现。由于它存储在内存中,因此它仍然是进程绑定的。