WIF 密钥在指定状态下无效

WIF Key not valid for use in specified state

我的 Web 应用程序使用 WIF 根据他们自己的 STS 对用户进行身份验证(我无法控制他们的 STS 的设置方式,我只是将 url 提供给联合元数据).

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

当只有 1 个用户使用唯一的 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) 

我该如何解决这个错误,或者对诊断这个问题有什么帮助?

对于以后寻找相同问题的任何人,这里的信息解决了我的问题。 http://weblogs.asp.net/cibrax/the-system-cannot-find-the-file-specified-error-in-the-wif-fam-module(下面文章的副本)

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

但是,从我的角度来看,这种技术有一些严重的缺点,使其无法用于实际的企业场景。

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

DPAPI不​​适合web farm场景,因为机器密钥是用来保护cookie的。如果cookie是用一个密钥保护的,那么后面的请求必须发到同一台机器上。一个解决方法是使用粘性会话,这样来自同一台机器的所有用户请求都由场中的同一台机器处理。

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

“SecuritySessionHandler”是 WIF 中的处理程序,负责将身份验证会话跟踪到 cookie 中。该处理程序默认接收一些内置 类 将转换应用于 cookie 内容,例如 DeflatCookieTransform 和 ProtectedDataCookieTransform(用于使用 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");