使用wsHttpBinding和Message Security与客户端凭据类型窗口负载平衡WCF

时间:2014-07-31 09:14:27

标签: c# wcf load-balancing wcf-security ws-security

我们有一个普通的WCF服务,其绑定看起来像这样:

 <wsHttpBinding>
 <binding name="ServiceBinding" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxReceivedMessageSize="20971520"
                messageEncoding="Mtom" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">                   
                <security mode="Message">
                      <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        establishSecurityContext="false" />
                </security>
            </binding>
</wsHttpBinding>

此服务位于负载均衡器后面的2台服务器中。正如这里建议的那样

http://msdn.microsoft.com/en-us/library/vstudio/hh273122(v=vs.100).aspx

我已将establishSecurityContext设置为false。当我运行调用服务时,我得到与无效安全上下文令牌相关的间歇性问题。即使我说不要建立SeurityContext,似乎WCF正在做所有正常的握手事情。

此时使用Cert,BasicHttBinding或由于要求,不能选择安全性。

我甚至让基础架构团队在负载均衡器中启用粘性会话,但似乎没有任何工作方式符合预期。

我和我的团队几乎完成了互联网上所说的一切,但是当有负载均衡器时似乎没有任何工作,并且当没有负载均衡器时,这种绑定工作正常。

有没有人对此绑定感到满意?

我们正在追逐微软向我们发送WCF专家,但显然人们很难掌握。

我怎样才能让这个东西与Load Balancer很好地配合?

2 个答案:

答案 0 :(得分:7)

您设置negotiateServiceCredential =&#34; true&#34;。这意味着在初始交换期间会创建安全上下文,但这种上下文不会在后续调用中使用(因为establishSecurityContext =&#34; false&#34;)。协商过程允许客户端安全地获取服务器凭据。然后,客户端使用这些凭据来保护消息。这就是为什么所有&#34;握手的东西&#34;发生的情况。

本文描述了这种情况:"Message Security with a Windows Client"

当您使用负载均衡器时需要进行安全协商(因为实际服务器的凭据取决于将为请求提供服务的计算机),除非您为后面的所有服务实例使用相同的凭据平衡器。在后一种情况下,您可以设置negotiateServiceCredential =&#34; false&#34;并在配置或代码中指定服务器凭据。例如,您可以使用clientCredentialType =&#34; Certificate&#34;并为所有计算机使用相同的服务器证书。或者你可以clientCredentialType =&#34; Windows&#34;并为域用户配置任意SPN,域用户用于运行平衡器后面的所有服务(我没有尝试这种情况,请参阅下面的详细信息)。

在您的情况下,negotiateServiceCredential =&#34; true&#34;。所以可能的问题是:

1)粘性会话可能无法正常工作。您可以通过使用返回

的BasicHttBinding实现简单的WCF服务来测试它
String.Format("{0}{1}", prefix, DateTime.Now);

配置前缀=&#34;&#34;在应用程序设置中,在一台服务器后面的平衡器和前缀=&#34; !!!!!!!!!!!!&#34;另外一个。然后多次循环调用此服务并记录结果。您将看到粘性会话是否存在问题。

2)如果粘性会话正常工作,请确保在未使用平衡时,您的配置适用于所有服务器。

如果您不能使用粘性会话,则应设置negotiateServiceCredential =&#34; false&#34;。未使用协商,因此客户端应在代码或配置中显式配置服务器凭据。要在未经协商的情况下使用Windows凭据类型,服务的用户帐户必须能够访问向Active Directory域注册的服务主体名称(SPN)。请参阅"Message Security with a Windows Client without Credential Negotiation"

中的详细信息和示例

要使用任意SPN,您应将服务配置为在同一Windows域帐户下运行。要将任意SPN设置为帐户,您可以在域控制器上使用setspn实用程序:

setspn a AcmeService/GlobalBank WS_Account

Kerberos Technical Supplement for Windows

中所述

有关各种方案和相应设置的说明,另请参阅有关Message Security的文章。

答案 1 :(得分:1)

如前所述,一种选择是关闭negotiateServiceCredential和establishSecurityContext。这将导致性能损失,这可能对您的方案有意义,也可能没有意义。如果这种方法也不起作用,那么由于kerberos / ntlm可能没有“一次性”认证。我建议只为一个用户操作(一个代理调用)打开Fiddler(或wcf日志),看看它是否只对服务器进行一次XML调用,或者是否需要多次调用进行身份验证。

另一个选择是确保所有服务器都使用Ivan提到的同一帐户。

还有第三种方法可以使用无状态安全上下文令牌使服务器无状态。只需设置:

requireSecurityContextCancellation=false

通过这种方式,所有客户端每次都会将cookie发送到服务器,因此无论他们获得哪个服务器都无关紧要。我知道,对于证书安全性,这意味着所有服务器必须使用相同的证书,不确定Windows安全性中的含义是什么。这是一个完整的例子:

http://msdn.microsoft.com/en-us/library/ms731814(v=vs.90).aspx

在某些情况下,创建自定义SecurityStateEncoder可能也是相关的:

http://msdn.microsoft.com/en-us/library/system.servicemodel.security.secureconversationservicecredential.securitystateencoder.aspx