【问题标题】:WIF Key not valid for use in specified stateWIF 密钥在指定状态下无效
【发布时间】:2016-02-11 22:54:53
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# single-sign-on wif adfs


    【解决方案1】:

    对于将来寻找相同问题的任何人,此处的信息解决了我的问题。 http://weblogs.asp.net/cibrax/the-system-cannot-find-the-file-specified-error-in-the-wif-fam-module(以下文章复制)

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

    但是,从我的角度来看,这种技术有一些严重的缺点,这使得它在实际的企业场景中毫无用处。

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

    DPAPI 不适合网络农场场景,因为机器密钥用于保护 cookie。如果 cookie 使用一个密钥进行保护,则必须将以下请求发送到同一台机器。解决此问题的方法可能是使用粘性会话,因此来自同一台机器的所有用户请求都由场中的同一台机器处理。

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

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

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

    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");
    

    【讨论】:

      猜你喜欢
      • 2012-01-04
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 2014-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多