C# WIF密钥在指定状态下无效

C# WIF密钥在指定状态下无效,c#,single-sign-on,wif,adfs,C#,Single Sign On,Wif,Adfs,我的web应用程序使用WIF根据用户自己的STS对用户进行身份验证(我无法控制如何设置他们的STS,我只给他们联邦元数据的url) 我的web应用程序运行在2个负载平衡器上,后面有2台服务器,我还使用粘性会话,在它们上有1小时的超时,并且两台机器共享相同的机器密钥,我在IIS中将LoadUserProfile设置为true 当只有一个用户使用唯一的STS登录时,它似乎可以正常工作,但一旦有一个以上的STS登录,我就可以看到以下错误在短时间内多次登录到服务器上 Key not valid for

我的web应用程序使用WIF根据用户自己的STS对用户进行身份验证(我无法控制如何设置他们的STS,我只给他们联邦元数据的url)

我的web应用程序运行在2个负载平衡器上,后面有2台服务器,我还使用粘性会话,在它们上有1小时的超时,并且两台机器共享相同的机器密钥,我在IIS中将LoadUserProfile设置为true

当只有一个用户使用唯一的STS登录时,它似乎可以正常工作,但一旦有一个以上的STS登录,我就可以看到以下错误在短时间内多次登录到服务器上

 Key not valid for use in specified state. 
Stack Trace: at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) at Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded)\r\n at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) at Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded) 

我如何解决此错误,或者如何帮助诊断此问题?

对于将来寻找相同问题的人,此处的信息修复了我的问题。(以下文章的副本)

作为WIF的一部分提供的联合身份验证模块(FAM)在默认情况下使用DPAPI保护会话cookie不被篡改。正如我在过去提到的,这种技术大大简化了整个解决方案的初始部署,因为不需要额外配置,自动生成的DPAPI密钥用于保护cookie,因此这可能是在WSE、WCF和现在的WIF中将其作为默认保护机制的原因

然而,在我看来,这种技术有一些严重的缺点,这使得它对真正的企业场景毫无用处

如果依赖FAM对用户进行身份验证的web应用程序托管在IIS中。运行IIS进程的帐户需要创建配置文件才能使用DPAPI。解决方法是使用该帐户登录计算机以创建初始配置文件或运行一些脚本来自动执行此操作

DPAPI不适用于web场场景,因为机器密钥用于保护cookie。如果cookie受一个密钥保护,则必须将以下请求发送到同一台计算机。解决方法是使用粘性会话,因此来自同一台机器的所有用户请求都由服务器场上的同一台机器处理

幸运的是,WIF已经提供了一些内置类,用一种基于带有X509证书的RSA密钥的保护机制来替换此默认机制

“SecuritySessionHandler”是WIF中负责将身份验证会话跟踪到cookie中的处理程序。该处理程序默认接收一些将转换应用于cookie内容的内置类,例如deflatCookietTransform和protectedDataCookietTransform(用于使用DPAPI保护内容)。还有另外两个CookieTransform派生的类根本没有使用,并且非常方便地启用企业场景,即RSAEncryptionCookieTransform和RSASignatureCookieTransform类。这两个类都接收用于加密或签名cookie内容的RSA密钥或X509证书

因此,您可以将以下代码放入global.asax文件中,用使用X509证书的转换替换默认cookie转换

protected void Application_Start(object sender, EventArgs e)
    {
        FederatedAuthentication.ServiceConfigurationCreated += new EventHandler<Microsoft.IdentityModel.Web.Configuration.ServiceConfigurationCreatedEventArgs>(FederatedAuthentication_ServiceConfigurationCreated);

    }

    void FederatedAuthentication_ServiceConfigurationCreated(object sender, Microsoft.IdentityModel.Web.Configuration.ServiceConfigurationCreatedEventArgs e)
    {
        var cookieProtectionCertificate = CertificateUtil.GetCertificate(StoreName.My,
            StoreLocation.LocalMachine, "CN=myTestCert");

        e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(
            new SessionSecurityTokenHandler(new System.Collections.ObjectModel.ReadOnlyCollection<CookieTransform> (
                new List<CookieTransform>
                {
                    new DeflateCookieTransform(),
                    new RsaEncryptionCookieTransform(cookieProtectionCertificate),
                    new RsaSignatureCookieTransform(cookieProtectionCertificate)
                })
            ));
    } 
var cookieProtectionCertificate = CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=myTestCert");