如何修复 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 应用程序?