如何修复HTTPS Silverlight应用程序上下文中的WCF maxClockSkew问题?

时间:2010-10-19 19:08:45

标签: silverlight wcf security binding https

情境:Silverlight 4应用程序通过WCF与服务器组件通信,使用basicHttpBinding和HTTPS。

以下是使用服务器端的绑定:

<basicHttpBinding>
<binding name="DefaultSecuredBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
      <readerQuotas maxDepth="50" maxArrayLength="2147483647" maxStringContentLength="2147483647" />
      <security mode="TransportWithMessageCredential">
        <message clientCredentialType="UserName"/>
        <transport clientCredentialType="None" proxyCredentialType="None"/>
      </security>
    </binding>
</basicHttpBinding>

请注意,我们使用 TransportWithMessageCredential 作为安全模式。 证书已在IIS上正确安装。

应用程序在本地运行时运行顺畅。

但是,我们现在有外部用户连接到我们的应用程序。 他们中的一些人遇到了困难,在服务器日志中查看,我们发现了这个错误:

“MessageSecurityException” 安全时间戳是陈旧的,因为其过期时间('2010-10-18T22:37:58.198Z')已过去。当前时间是'2010-10-18T22:43:18.850Z'并允许时钟偏差是'00:05:00'。

我们对网络主题(StackoverFlow&amp; Google ...和Bing)进行了常规研究,以便详细了解该主题。 我们联系了用户,以确保他们与我们的服务器的时间偏移,后来得到确认。

这篇MSDN文章的开头是: http://msdn.microsoft.com/en-us/library/aa738468.aspx

在现有绑定上使用CustomBinding,并在自定义绑定的SecurityBindingElement上设置MaxClockSkew属性。 我们实现了这个解决方案,将SymmetricSecurityBindingElement更改为TransportSecurityBindingElement,因为我们绑定了与Silverlight的安全通信 是使用HTTPS的basicHttpBinding。

网上的一些文章(包括上面列出的这篇MSDN文章)显示了代码片段,它还将maxClockSkew属性设置为取自 ProtectionTokenParameters 的引导元素。 我从未成功在代码中应用此部分,因为 TransportSecurityBindingElement 似乎没有任何 ProtectionTokenParameters

以下是使用maxClockSkew包装绑定的代码:

protected virtual System.ServiceModel.Channels.Binding WrapClockSkew(System.ServiceModel.Channels.Binding currentBinding)
    {
        // Set the maximum difference in minutes
        int maxDifference = 300;

        // Create a custom binding based on an existing binding
        CustomBinding myCustomBinding = new CustomBinding(currentBinding);

        // Set the maxClockSkew
        var security = myCustomBinding.Elements.Find<TransportSecurityBindingElement>();
        if (security != null)
        {
            security.LocalClientSettings.MaxClockSkew = TimeSpan.FromMinutes(maxDifference);
            security.LocalServiceSettings.MaxClockSkew = TimeSpan.FromMinutes(maxDifference);
        }


        return myCustomBinding;
    }

'security.LocalClientSettings'在这里可能没用,因为这段代码是服务器端的。

此代码没有执行操作,当我们与服务器的差异超过5分钟时,我们仍然在服务器上显示相同的错误消息。 我仍然记得我们没有应用MSDN代码片段的引导技巧..所以我们继续我们关于该主题的网络搜索。

我们发现了一个整洁的wcf行为,我们认为这会解决我们的问题。

看起来它处理Bootstrap绑定问题!

以下是在TransportSecurityBindingElement的上下文中搜索令牌参数的部分:

//If the securityBindingElement's type is TransportSecurityBindingElement
if (securityBindingElement is TransportSecurityBindingElement)
{
foreach (SecurityTokenParameters securityTokenParameters in 
    securityBindingElement.EndpointSupportingTokenParameters.Endorsing)
{
    //Gets it from the EndpointSupportingTokenParameters.Endorsing property
    if (securityTokenParameters is SecureConversationSecurityTokenParameters)
    {
        secureConversationSecurityTokenParameters =
            securityTokenParameters as SecureConversationSecurityTokenParameters;

        break;
    }
}
}

请注意'securityBindingElement.EndpointSupportingTokenParameters.Endorsing' ... 在我们的情况下(basicHttpBinding,TransportWithMessageCredential,Https ...),这个集合是空的!

所以,无法检索securityTokenParameters,因此无法设置maxClockSkew。

问题:

  • 我们的绑定在SL + WCF + HTTPS上下文中是否不正确?

  • 找不到任何方法在TransportSecurityBindingElement中的bootstrap元素上设置maxClockSkew是否正常?

  • 我们是唯一一家与客户进行HTTPS Silverlight应用的公司,可能不是同一时间(偏移+ - 5分钟)吗?

  • 为什么修复这么简单的配置似乎是一次冒险?

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:5)

以下代码段允许您在TransportSecurityBindingElement上设置maxClockSkew。我的解决方案是在http和https上下文中运行的Outlook加载项+ WCF,因此尽管与您的上下文不完全相同。

  • 您的绑定对我来说是正确的。
  • 以下是代码段

    WSHttpBinding wsSecureBinding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential, false);
    wsSecureBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
    wsSecureBinding.Security.Message.EstablishSecurityContext = true;
    wsSecureBinding.Security.Message.NegotiateServiceCredential = true;
    wsSecureBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    wsSecureBinding.ReaderQuotas.MaxStringContentLength = 500000;
    wsSecureBinding.ReceiveTimeout =
    wsSecureBinding.SendTimeout = new TimeSpan(0, 5, 0);
    CustomBinding secureCustomBinding = new CustomBinding(wsSecureBinding);
    TimeSpan clockSkew = new TimeSpan(0, 15, 0);
    
    TransportSecurityBindingElement tsecurity = secureCustomBinding.Elements.Find();
    SecureConversationSecurityTokenParameters secureTokenParams = (SecureConversationSecurityTokenParameters)tsecurity.EndpointSupportingTokenParameters.Endorsing.OfType().FirstOrDefault();
    if (secureTokenParams != null)
    {
        SecurityBindingElement bootstrap = secureTokenParams.BootstrapSecurityBindingElement;
        // Set the MaxClockSkew on the bootstrap element.
        bootstrap.LocalClientSettings.MaxClockSkew = clockSkew;
        bootstrap.LocalServiceSettings.MaxClockSkew = clockSkew;
    } 
  • 时钟偏差仅在您使用UserName客户端凭据时有用,而某些用户要么计算机时钟不正确,要么他们不在乎

  • 是的,WCF配置始终是您不想做的冒险。

答案 1 :(得分:0)

我们在这里遇到同样的问题!有关进一步的讨论,如果这篇文章可以提供帮助,那么搜索令牌参数的代码就是从这个站点获取的

http://issues.castleproject.org/_persistent/MaxClockSkewBehavior.cs?file=44-1075&v=0&c=true

答案 2 :(得分:0)

您是否尝试过更改为配置(而不是代码)中的自定义绑定并更改maxClockSkew?参见例如在http://social.msdn.microsoft.com/forums/en-US/wcf/thread/0e8c30ab-e5a0-40b1-9722-c1b20a09c8ad/

中配置示例