再一次尝试让我的WCF服务在我们的负载平衡环境中工作,我一直充满希望。我已经开始使用<customBinding>
了,因为recommendation似乎是设置keepAliveEnabled
指令。
也就是说,我在服务器端设置Windows身份验证时遇到问题,因为<customBinding>
似乎没有以相同的方式运行。
服务器端看起来像这样:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<bindings>
<customBinding>
<binding name="HttpBinding" closeTimeout="00:00:45">
<textMessageEncoding>
<readerQuotas maxStringContentLength="200000" maxArrayLength="200000" />
</textMessageEncoding>
<httpTransport keepAliveEnabled="false" maxReceivedMessageSize="200000" authenticationScheme="Negotiate"/>
</binding>
</customBinding>
</bindings>
<services>
<endpoint address="http://svcserv/Services/ReportService/Reports.svc" binding="customBinding"
bindingConfiguration="HttpBinding" contract="ReportService.IReports" >
</endpoint>
<endpoint address="mex" binding="customBinding" bindingConfiguration="HttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ReportService.ReportsBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
客户端看起来像这样:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<bindings>
<basicHttpBinding>
<binding name="CustomBinding_IReports" maxReceivedMessageSize="200000">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="CustomBinding_IReports" address="http://omsnetdev/Services/ReportService/Reports.svc"
binding="basicHttpBinding" bindingConfiguration="CustomBinding_IReports" contract="ReportService.IReports">
<identity>
<servicePrincipalName value="host/svcserv"/>
<dns value="svcserv"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
如果我将authenticationScheme设置为“Negotiate”,那么我会收到SOAP header Action was not understood.
或Client found response content type of '', but expected 'application/soap+xml'.
的某些内容,Exception: The request failed with HTTP status 401: Unauthorized.
如果我将authenticationScheme更改为“Ntlm”,那么我会收到{{1}}但我认为这是由于协商失败(due to the SPN value?)所以它会回落到“Ntlm”并失败。
我会在IIS服务器上将其写为配置,但我已验证了设置。
答案 0 :(得分:4)
我认为这不仅是WCF问题,而且是概念模型。您希望完全构建无状态方案,但同时需要有状态地处理身份验证,因为在单个请求响应中执行NTLM(并且没有其他传输级别身份验证)。
以下简要说明握手的工作原理:
Client Server
-----------------------------------------------------------------------------------------
Send initial request ---------------------------->
<---------------------------- Returns 401 with WWW-Authenticate
header demanding NTLM
Sends empty request ---------------------------->
with Authorization
header with initial
token
<---------------------------- Returns 401 with WWW-Authenticate
header containing some server token
Sends request with ---------------------------->
Authorization header
with final token
<---------------------------- Returns 200 and expected response
此握手必须使用单个负载平衡服务器执行,但是一旦关闭持久HTTP连接,您将强制客户端为每个呼叫打开新的TCP连接,并且每个呼叫都是单独负载平衡的。这很可能会以传递给不同服务器的这些调用结束=&gt;验证失败。简而言之,您需要:
答案 1 :(得分:1)
如果您遇到与SPN相关的问题,请参阅以下答案:SO WCF-Security-Problem question
您应该在负载均衡器上遇到的唯一问题是您是否需要会话对一个主机保持“粘性”。对于给定的会话,如果正确配置,负载均衡器应该能够为您执行此操作。
请注意,如果您在同一台计算机上安装了服务器和客户端,则Windows服务器具有不使用SSPI的回退模式。当你从测试移动到prod时,这会让你被烧掉。