负载均衡器后面的WCF服务的WSDL生成

时间:2012-06-01 10:22:07

标签: wcf ssl load-balancing svcutil.exe

背景:

我在一个负载均衡器后面的IIS 7.0上托管了一个服务,当流量通过它时会对SSL进行解密。

服务所需的安全模式是混合模式,即TransportWithMessageSecurity

要使服务接受HTTP流量,同时允许客户端通过SSL与Load Balancer进行通信,我创建了一个用户定义绑定,它将自定义HttpTransportBindingElement添加到其通道堆栈。

自定义HttpTransportBindingElement依次向框架声明它能够加密和签名消息...因此,当流量通过HTTP进入时,框架不会抱怨,因为Transport声称它正在签名/加密消息......即使它不是。

对于所有相关人员,已经确定这是安全明智的,因为消息或者应该通过SSL到达负载均衡器......

问题:

当我们使用svcutil.exe生成客户端代理时,生成的自动生成的app.config文件包含通过HTTP寻址的服务的端点。 这应该通过HTTPS

另外< transport> < customBinding>中的元素节点被定义为< httpTransport> 时需要的元素是< httpsTransport>元件

我怀疑这是因为服务器上的框架生成的WSDL是使用HTTP地址而不是HTTPS构建的。反过来,由于使用自定义HttpTransportBindingElement(如上所述)。

自动生成的客户端app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
    <bindings>
        <customBinding>
            <binding name="myBindingEndpoint">
                <!--    WsdlImporter encountered unrecognized policy assertions in ServiceDescription 'http://tempuri.org/':    -->
                <!--    <wsdl:binding name='myBindingEndpoint'>    -->
                <!--        <sp:HttpToken xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">..</sp:HttpToken>    -->
                <security defaultAlgorithmSuite="Default" authenticationMode="CertificateOverTransport"
                    requireDerivedKeys="true" securityHeaderLayout="Strict" includeTimestamp="true"
                    keyEntropyMode="CombinedEntropy" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
                    <localClientSettings cacheCookies="true" detectReplays="false"
                        replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite"
                        replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00"
                        sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="true"
                        timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" />
                    <localServiceSettings detectReplays="false" issuedCookieLifetime="10:00:00"
                        maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00"
                        negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00"
                        sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00"
                        reconnectTransportOnFailure="true" maxPendingSessions="128"
                        maxCachedCookies="1000" timestampValidityDuration="00:05:00" />
                    <secureConversationBootstrap />
                </security>
                <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
                    messageVersion="Default" writeEncoding="utf-8">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                </textMessageEncoding>
                <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
                    maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
                    bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
                    keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
                    realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                    useDefaultWebProxy="true" />
            </binding>
        </customBinding>
    </bindings>
    <client>
        <endpoint address="http://myserver/GAEASSLWcfService/ServiceOverSSL.svc"
            binding="customBinding" bindingConfiguration="myBindingEndpoint"
            contract="IServiceOverSSL" name="myBindingEndpoint" />
    </client>
</system.serviceModel>
</configuration>

解决方法:

只需更改&lt; httpTransport /&gt;到&lt; httpsTransport /&gt;并重新寻址端点以使用HTTPS修复该问题。

但我们宁愿不必指示我们的服务消费者更改他们的.config文件......我们的服务的使用应该尽可能无缝......

问题:

如何确保客户端代理将使用正确的地址和传输元素自动生成???

参考文献: 对于那些想要了解“负载均衡器/ ssl解密器背后的服务”和自定义HttpTransportBindingElement的解决方案的人,请参阅这篇文章XXX by ZZZ关于构建用户定义的绑定以及此帖子XXX由ZZZ关于一些在负载平衡/ SSL加速器后面公开服务的其他问题。

2 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,我的WSDL是使用http方案而不是我负载均衡器后面的https生成的。

我已经反映了WCF代码,但我发现了一个适合我的解决方案。

除了useRequestHeadersForMetadataAddress之外,还需要关闭httpGetEnabled并在serviceMetadata中打开httpsGetEnabled。

此外,如果您使用的是.net 4,我认为您可以使用标准的HttpTransportBindingElement,而不是添加自定义的HttpTransportBindingElement,并在TransportSecurityBindingElement上设置AllowInsecureTransport。

答案 1 :(得分:0)

结帐this question。尝试配置:

<serviceBehaviors>
   <behavior name="<name>">
     <!-- Other options would go here -->
     <useRequestHeadersForMetadataAddress>
       <defaultPorts> <!-- Use your own port numbers -->
          <add scheme="http" port="81" />
          <add scheme="https" port="444" />
        </defaultPorts>
      </useRequestHeadersForMetadataAddress>
   </behavior>
</serviceBehaviors>