MVC 6 WebFarm:防伪令牌无法解密

8

我正在一个Webfarm场景中运行MVC 6(vNext)(使用具有多个AppServers的ARR前端)。服务器亲和性关闭。

当我在不同请求之间跳转到应用程序服务器时,会出现以下错误:

CryptographicException:在密钥环中找不到密钥{3275ccad-973d-43ca-930f-fbac4d276640}。

InvalidOperationException:无法解密防伪令牌。

以前,我认为可以通过在web.config中设置静态MachineKey来处理此问题。

据我了解,我们现在已经转向了新的DataProtection API,并尝试了以下方法,认为应用程序名称作为某种种子:

        services.AddDataProtection();
        services.ConfigureDataProtection(configure =>
        {                
            configure.SetApplicationName("WebAppName");
        });

现有的方法无法解决这个问题。

在vNext中有什么解决办法么?


除了被接受的答案之外,现在在 Redis 上持久化数据保护密钥非常容易,并且在 Web Farm 场景下运行良好。请参见 http://www.tugberkugurlu.com/archive/asp-net-core-authentication-in-a-load-balanced-environment-with-haproxy-and-redis。 - tugberk
1个回答

7

解释

您需要重复使用相同的密钥。

如果您在Azure上,密钥会通过NAS类型存储在%HOME%\ASP.NET\DataProtection-Keys上进行同步。

对于本地运行的应用程序,它们存储在运行应用程序的用户的%LOCALAPPDATA%\ASP.NET\DataProtection-Keys中,或者如果在IIS中执行,则存储在注册表中。

如果以上都不匹配,则为进程的生命周期生成密钥。

解决方案

因此,第一种选项不可用(仅适用于Azure)。但是,您可以在每台运行您的应用程序的计算机上将密钥从运行应用程序的用户的%LOCALAPPDATA%\ASP.NET\DataProtection-Keys进行同步。

但更好的方法是,您可以像这样将其指向网络共享:

sc.ConfigureDataProtection(configure =>
{
    // persist keys to a specific directory
    configure.PersistKeysToFileSystem(new DirectoryInfo(@"Z:\temp-keys\"));
});

这将使您能够在保持安全性的同时进行扩展。

重要提示:您的密钥将每90天过期。频繁重新生成密钥非常重要。

您可以使用以下代码更改它,但是长度越短,越安全。

services.ConfigureDataProtection(configure =>
{
    // use 14-day lifetime instead of 90-day lifetime
    configure.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
});

源代码


太棒了。谢谢你。这是一个本地部署(非 Azure)。因此,选择这个选项,我们是否意味着应用程序只有在网络共享在线时才能运行?与 machineconfig 键相比,似乎是一个脆弱的关键点,不是吗? - Simon Ordo
1
是的和不是的。如果应用程序经常被访问,密钥会提前2天生成,一旦它们被读取,所有操作都来自内存。他们将在内存中缓存这些密钥,直到需要再次更新它们。 - Maxime Rouiller
谢谢! 那么除了网络共享之外,现在没有其他的跨机器共享密钥的机制了吗? - Simon Ordo
1
是的,但现在你更接近核心了。有一个IXmlRepository 接口可以用来改变存储方式。内置了3种:文件,注册表和内存。您可以重新实现自己的存储方式,并在ConfigureServices部分中定义它。 - Maxime Rouiller
3
我注意到似乎可以通过调用“PersistKeysToFileSystem”并指定本地路径来滥用API,并在我的测试环境中运行以生成密钥文件。如果我将该密钥文件复制到Webfarm中的所有计算机(相对路径相同),看起来也可以工作。显然,这种方法无法在旋转旧密钥时使用,但是如果过期时间足够长,这一部分就不成问题了。当然,这种方法似乎绕过了API提供的许多好处,但为了讨论的缘故,我还是想提一下。 - Simon Ordo
@MaximeRouiller 如果您通过Azure Blob存储进行存储,并上传预先存在的数据保护密钥,则会使用这些密钥而不是生成新的密钥? - gdp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接