DPAPI与IIS和ASP.NET MVC使用CurrentUser时出现的间歇性“密钥在指定状态下无效”例外

问题描述

我们有两台服务器在IIS下运行相同的ASP.NET MVC应用程序。服务器A在Windows Server 2008 R2 Standard v 6.1内部版本7601 SP1上运行IIS 7.5。服务器B在Windows Server 2012 R2 v 6.3内部版本9600上运行IIS 8.5。

应用程序池在同一Windows用户下运行。

该Web应用程序将ProtectedData.Protect和Unprotect与DataProtectionScope CurrentUser一起使用,并将加密后的值存储到单独的数据库中(两个服务器之间完全没有交互)

服务器A已经运行了一年多,并且有两次或三次无法解密(错误消息“解密失败:密钥在指定状态下无效”)。我们不了解其原因,只是通过应用程序重新加密了值。由于这种情况很少发生,因此我们决定可以接受。

服务器B已经运行了大约3周,在同一时间中,该问题已发生5次。我们不能忍受这个,因此我问这个问题。

IIS高级设置中的“加载用户配置文件”设置在两台服务器上都是正确的,并且贯穿始终。

我们最初的想法是,应用程序池标识的用户可能正在发生变化。但是,由于两个应用程序都在同一用户下运行,并且服务器B发生故障时,即使在IISRESET和重新启动之后,服务器A仍可以工作,因此我们将其排除在外。

据我们所知,两台服务器上的设置相同(在可能的范围内,因为它们是不同的操作系统和IIS版本)

有人能想到这种情况发生的原因吗?预先感谢。

解决方法

确保在iis应用程序池高级设置中将“加载用户配置文件”设置为true。

enter image description here

编辑:

只有本地操作系统可以访问此计算机密钥,该密钥对于每次安装都是唯一的。 Windows支持使用此密钥保护数据的DPAPI。使用此API时,您无权直接访问密钥。您可以要求系统使用机器的密钥加密或解密某些内容。这样,您的应用程序可以通过DPAPI加密它使用的密钥,并且.NET Framework支持System.Security.Cryptography.ProtectedData类。

  • 当您想使用ProtectedData类来保护敏感信息时,应该添加对System.Security.dll程序集的引用并导入System.Security.Cryptography命名空间。可能的范围是LocalMachine和CurrentUser。

  • 要使用机器密钥时可以选择LocalMachine。

  • 当您要使用为当前登录用户的个人资料生成的密钥时,可以选择CurrentUser。如果Active Directory漫游配置文件允许在Active Directory域内的多台Windows计算机上重用Windows用户配置文件,则此密钥与计算机无关。

  • 机器管理员可以通过编写调用前一个功能的程序来解密数据。

  • 如果用户不是管理员,也没有使用DPAPI的权限,则他/她无法解密使用计算机密钥加密的数据。

  • 您不应使用DPAPI对数据库中的信息进行加密,因为如果使用DataProtectionScope.LocalMachine设置,则加密的数据将绑定到计算机。如果计算机崩溃,并且您必须在另一台计算机上还原数据,则将丢失所有加密信息。

  • 如果您使用DPAPI如前所述对密钥进行加密,则应该在另一个安全的地方备份密钥。

  • 如果要在Web服务器场方案中使用DPAPI,则必须以域用户帐户运行应用程序,并使用为用户的配置文件创建的密钥(DataProtectionScope.CurrentUser)。您应该为您的Web场创建一个单独的域,这样就不必使用公司内部域网络的域用户。

参考链接:

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata?view=dotnet-plat-ext-3.1

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata.unprotect?view=dotnet-plat-ext-3.1

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata.protect?view=dotnet-plat-ext-3.1