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

Posted

技术标签:

【中文标题】如何修复 HTTPS Silverlight 应用程序上下文中的 WCF maxClockSkew 问题?【英文标题】:How to fix the WCF maxClockSkew problem in a HTTPS Silverlight application context? 【发布时间】:2011-04-27 16:08:31 【问题描述】:

情况: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”。

我们对网络上的主题(*** 和 Google... 和 Bing)进行了常规研究,以阅读有关该主题的更多信息。 我们联系了用户,以确保他们与我们的服务器有时间偏移,后来得到了确认。

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

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

网络上的几篇文章(包括上面列出的这篇 MSDN 文章)显示了代码 sn-ps,它另外将 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 代码 sn-p 的引导技巧。所以我们继续在网络上搜索该主题。

我们发现了一个简洁的 wcf 行为,我们认为它可以解决我们的问题。

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

这是它在 TransportSecurityBindingElement 的上下文中搜索 Token Parameters 的部分:

//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 中的引导元素上设置 maxClockSkew 是否正常?

我们是唯一一家使用 HTTPS Silverlight 应用程序的公司,其客户可能不在同一时间(有 +- 5 分钟偏移)?

为什么修复如此琐碎的配置似乎是一件很冒险的事?

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

以下代码 sn-p 允许您在 TransportSecurityBindingElement 上设置 maxClockSkew。我的解决方案是在 http 和 https 上下文中运行的 Outlook 加载项 + WCF,因此虽然与您的上下文不同,但它相似。

您的绑定在我看来是正确的。

这里是代码sn-p

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 配置始终是您不愿做的冒险。

【讨论】:

这听起来很有希望。我会试试这个,如果它解决了我们的问题,我会告诉你。同时,我们决定从消息中删除时间信息,因为我们不需要它。如果未发送时间信息,则不会检查时钟偏差验证。非常感谢! 如果您能提供有关如何删除时间信息的信息,我想很多人会感激不尽。例如。现在我可以从中受益。 :) 提前致谢! 您要删除什么时间信息?时钟歪斜时间信息?如果是,那么您需要为 clientCredentialType 属性选择一个备用值,因为时钟偏差用于保证用户名和密码的安全。 感谢您的帮助。不幸的是,我无法更改 ClientCredentialType。我得去别的地方打猎了。【参考方案2】:

我们在这里遇到了同样的问题!!!为了进一步讨论,如果这篇文章可以帮助,它搜索令牌参数的代码取自该站点

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于如何修复 HTTPS Silverlight 应用程序上下文中的 WCF maxClockSkew 问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何分析 Silverlight 应用程序?

XAML silverlight 中的填充图案

如何布局 Silverlight 应用程序?

如何针对已部署的服务 [跨域问题] 调试 Silverlight 应用程序?

如何确定是不是在 Silverlight 应用程序中切换了 Caps Lock?

缺少 Silverlight“业务应用程序”模板