我们有一个正常的 WCF 服务,它具有如下所示的绑定(bind):
<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。当我运行调用该服务时,我遇到与无效安全上下文 token 相关的间歇性问题。尽管我说不要建立 SeurityContext,但似乎 WCF 正在执行所有正常的握手操作。
此时,由于要求,使用 Cert、BasicHttBinding 或无安全性不是一种选择。
我什至让基础架构团队在负载均衡器中启用粘性 session ,但似乎没有任何效果像我们预期的那样工作。
我和我的团队几乎完成了互联网上所说的所有事情,但是当有负载均衡器时似乎没有任何效果,而当没有负载均衡器时此绑定(bind)工作完美。
有人幸运地使用了这个绑定(bind)吗?
我们正在争取 Microsoft dispatch WCF 专家,但显然很难找到人。
我怎样才能让这个东西与负载平衡器很好地协同工作?
最佳答案
您设置了 negotiateServiceCredential="true"。这意味着安全上下文是在初始交换期间创建的,但此上下文不会在后续调用中使用(因为 establishSecurityContext="false")。协商过程允许客户端安全地获取服务器凭据。然后客户端使用这些凭据来保护消息。这就是为什么所有“握手的事情”都会发生。
本文描述了这种情况:"Message Security with a Windows Client" .
当您使用负载均衡器时需要安全协商(因为实际服务器的凭据取决于将服务请求的机器),除非您对平衡器后面的所有服务实例使用相同的凭据。在后一种情况下,您可以设置 negotiateServiceCredential="false"并在配置或代码中指定服务器凭据。例如,您可以使用 clientCredentialType="Certificate"并为所有计算机使用相同的服务器证书。或者你可以 clientCredentialType="Windows"并为域用户配置任意 SPN,用于运行平衡器后面的所有服务(我没有尝试这种情况,请参阅下面的详细信息)。
在您的情况下,negotiateServiceCredential="true"。所以可能的问题是:
1) 粘性 session 可能无法正常工作。您可以通过使用返回的 BasicHttBinding 实现简单的 WCF 服务来测试它
String.Format("{0}{1}", prefix, DateTime.Now);
在平衡器后面的一台服务器上的应用程序设置中配置 prefix=""和 prefix="!!!!!!!!!!!!!”另外一个。然后多次循环调用此服务并记录结果。您会看到粘性 session 是否存在问题。
2) 如果粘性 session 正常工作,请确保您的配置在未使用平衡时适用于所有服务器。
当你不能使用粘性 session 时,你应该设置negotiateServiceCredential="false"。不使用协商,因此客户端应该在代码或配置中显式配置服务器凭据。要在不协商的情况下使用 Windows 凭据类型,服务的用户帐户必须有权访问在 Active Directory 域中注册的服务主体名称 (SPN)。请参阅 "Message Security with a Windows Client without Credential Negotiation" 中的详细信息和示例
要使用任意 SPN,您应该将您的服务配置为在同一 Windows 域帐户下运行。要为帐户设置任意 SPN,您可以在域 Controller 上使用 setspn 实用程序:
setspn a AcmeService/GlobalBank WS_Account
如 Kerberos Technical Supplement for Windows 中所述
另请参阅关于 Message Security 的文章用于描述各种场景和相应的设置。
关于c# - 使用 wsHttpBinding 和 Message Security 使用客户端凭据类型窗口对 WCF 进行负载平衡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25055078/