【问题标题】:WSDL Generation for WCF Service Behind Load Balancer负载均衡器后面的 WCF 服务的 WSDL 生成
【发布时间】:2012-06-06 14:11:15
【问题描述】:

背景:

我在负载均衡器后面的 IIS 7.0 上托管了一项服务,该服务在流量通过它时解密 SSL。

Service所需的安全模式是Mixed-Mode,即TransportWithMessageSecurity

为了使服务能够接受 HTTP 流量,同时允许客户端通过 SSL 与负载均衡器进行通信,我创建了一个用户定义的绑定,它将一个自定义 HttpTransportBindingElement 添加到其通道堆栈中。

自定义的 HttpTransportBindingElement 反过来向框架断言它能够加密和签署消息......因此,当流量通过 HTTP 通过它进入时,框架不会抱怨,因为传输声称它正在签名/加密消息...即使不是。

对于所有相关人员而言,这已被确定为可接受的安全性,因为消息原本应该通过 SSL 到达负载均衡器...

问题:

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

此外, 节点中的 元素在 需要是 元素时被定义为 元素。

我怀疑这是因为服务器上的框架生成的 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>

解决方法:

只需将 更改为 并重新寻址端点以使用 HTTPS 即可解决此问题。

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

问题:

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

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

【问题讨论】:

  • 您使用哪个 wcf 版本?我相信 .net 4 这个问题是固定的
  • 该项目的目标框架是 .Net 4.0 - 所以问题似乎没有解决。
  • 您是否曾经设法找到解决 wsdl 问题的方法。我们遇到了同样的问题

标签: wcf ssl load-balancing svcutil.exe


【解决方案1】:

查看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>

【讨论】:

  • 我已经阅读了这方面的内容,但认为它并不适用,因为我使用的是 .Net 4,并且此修复适用于以前的版本。但是,无论如何我确实尝试过,它似乎没有任何区别。即使通过 HTTPS 浏览 WSDL 仍然会导致 HTTP 寻址...如果我转到 HTTPS //mydomain/GAEASSLWcfService/ServiceOverSSL.svc?wsdl 代码,我会得到如下引用:HTTP //mydomain/GAEASSLWcfService/ServiceOverSSL.svc?xsd= xsd0
【解决方案2】:

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

我已经反映了 WCF 代码,但我找到了一个对我有用的解决方案。

除了useRequestHeadersForMetadataAddress,还需要在serviceMetadata中关闭httpGetEnabled,开启httpsGetEnabled。

另外,如果您像我认为的那样使用 .net 4,而不是添加自定义 HttpTransportBindingElement,只需使用标准 HttpTransportBindingElement 并在您的 TransportSecurityBindingElement 上设置 AllowInsecureTransport。

【讨论】:

  • 嗨,塞巴斯蒂安,感谢您的贡献。我早就离开了这个项目,所以无法检查你的答案是否能解决我的问题。但我会为你的努力 +1...
  • 没问题,谢谢。此外,为了能够使用负载均衡器后面的服务,除了地址之外,您还需要在端点上配置监听 uri。客户端,您需要在具有给定监听 uri 的端点上使用 ClientViaBehavior。这将修复 AddressFilter 不匹配错误。
  • 我遇到了与@JTech 完全相同的问题,上面的答案纠正了这个问题。唯一的问题是,在进行此修改后,WSDL 链接不再起作用。我仍然可以通过 ...Service.cs/mex 在 Visual Studio 中添加对我的服务的引用,但我希望 WSDL 能够解析。
猜你喜欢
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 2011-04-19
  • 2019-11-14
  • 2010-09-20
  • 2013-04-11
  • 1970-01-01
  • 2013-08-26
相关资源
最近更新 更多