WCF,元数据和BIGIP - 我可以为WSDL项强制使用正确的URL吗?
题
我们在ServerA上托管了一个WCF服务,该服务是一个无法直接访问Internet且具有非Internet可路由IP地址的服务器。
该服务由BIGIP提供,它处理SSL加密和解密,并将未加密的请求转发给ServerA(此时它实际上没有进行任何负载平衡,但可能会在将来添加)在特定端口上
这意味着我们的客户将通过 https://www.OurDomain.com/ServiceUrl调用该服务并通过BIGIP设备在 http:// SeverA:85 / ServiceUrl 上获得我们的服务;
当我们浏览 https://www.OurDomain.com/ServiceUrl 上发布的WSDL时WSDL中包含的地址基于 http:// SeverA:85 / ServiceUrl 基地
我们发现我们可以使用主机头设置来设置域,但我们的问题是虽然这会解析域,但我们仍然会使用错误的方案<!>#8211;它会使用 http://www.OurDomain.com/ServiceUrl ,而我们需要它是Https。
同样<!>#8211;因为我们在该服务器上托管了其他服务(基于asmx),我们在设置主机头时遇到了一些问题,所以我们认为我们可以在服务器上创建另一个站点(使用端口82)并设置主机头在那;现在,除了http / https问题之外,我们遇到了一个问题,因为WSDL包含所有URL中的端口号,其中BigIP在端口443(用于SSL)上工作
是否有比实施主机标头更灵活的解决方案?理想情况下,我们需要保持灵活性和易于支持性。
感谢您的帮助<!>#8230;
解决方案
这实际上是一个多部分问题,涉及许多离散的解决方案,以提供完整的答案。基本上坐在F5后面有3个问题。
- 公布的服务端点主机名。
- 描述数据合同的xsd:import'ed模式链接的主机名
- 您描述的http / https问题。 醇>
更改主机标头,因为您已找到解决方案1和2(您可以通过主机标头以外的方式处理此问题,但无需在此处进行此操作)。 3号有点棘手,需要更多代码(在这里转储太多)。
简短的回答是你需要编写一个实现IContractBehavior和IWsdlExportExtension的ContractBehavior。
您需要实现的重要位是IWsdlExportExtension.ExportEndpoint。在此方法中,您需要遍历所有WsdlPort扩展,当您找到类型为SoapAddressBinding的扩展时,您需要将SoapAddressBinding.Location属性替换为包含https协议说明符的新Uri。您还需要为xsd导入地址和架构链接执行类似的操作。
如果您的服务也使用WS-Addressing您需要执行类似的操作来处理它写入wsdl的其他地址。
我根据CodePlex上提供的WsdlExtras项目编写代码( http:// wcfextras。 codeplex.com/ )。 WsdlExtras中使用的方法为您可能需要添加的任何额外位提供了一个很好的基础(从内存中我不认为它处理WS-Addressing位)。您要查看的位是<!>“覆盖SOAP地址位置URL <!>”。
其他提示
感谢Mark Allanson,我和yossi dahan完全一样,WCFExtras.dll文件对我有用,
步骤1。下载WCFExtras.dll (http://www.codeplex.com/WCFExtras/) 。 点击 第2步。添加它对您的项目的引用。 点击 第3步。不要浪费你的时间来编写示例服务器应用程序中建议的任何代码。 点击 第4步。打开web.config并输入以下代码: 结果
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
结果
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehaviorName" name="ServiceName">
<endpoint address="" behaviorConfiguration="ServiceEndpointBehaviorName" binding="basicHttpBinding" contract="IServiceName">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="ServiceEndpointBehaviorName">
<wsdlExtensions location="https://sslLoadBalancer/ServiceName.svc"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviorName">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!-- Declare that we have an extension called WSDL Extras-->
<add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
结果
STEP5。同样重要的是要注意,如果您通过此URL添加引用"https://sslLoadBalancer/ServiceName.svc"
然后它将无法工作,请始终记住添加引用为:"https://sslLoadBalancer/ServiceName.svc?wsdl"
这样您就可以添加对您的应用程序的引用。
点击
点击
多数民众赞成......如果仍然无效,请告诉我,我将粘贴完整的web.config文件..
由于
如果您在现有服务之上添加SSL,它可能也会影响WCF客户端的绑定安全模式,您可以轻松覆盖它。
对于WSDL,为什么不直接下载文件,将URL更改为您想要的任何内容,并将其作为文件手动发布?
我得到了一个很好的建议,即将端点上的地址属性设置为您希望在WSDL中显示的URL,然后将一个listenUri属性添加到端点,并使用实际的Uri来监听。
测试页面中的Url不会受到影响(即它仍将显示ListenUri中指定的地址),但在WSDL中将设置正确的Uri(地址中指定的那个。
最令人讨厌的是,当我在发布问题后不久尝试了这个问题时,我无法让它在IIS中工作,只有在控制台应用程序中进行自托管时;今天检查自己,我发现它确实有效;所以现在我不确定为什么它之前对我不起作用;
我们在同一时间所做的是建立一个简单的自定义行为,它改变了服务描述,从而将WSDL中所需的地址从configurtion中删除;很明显,如果内置支持它会更好,所以下周我会花些时间来深入研究这个问题。
在服务类中添加属性:
<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>
这允许客户端将服务称为https:// ...但是要在http:// .....
上托管的服务在服务主机的web.config中,端点元素必须在address属性中具有绝对URL,该URL是客户端将使用的公共URL。在同一个端点元素中,将listenUri属性设置为服务主机正在侦听的绝对URL。我确定主机正在侦听的默认绝对URI的方式是在客户端应用程序中添加服务引用,该服务引用指向托管服务的物理服务器。客户端的web.config将具有该服务的地址。然后我将其复制到主机web.config中的listenUri属性中。
在您的服务行为配置中添加元素serviceMetaData,其属性为httpGetEnabled = true
所以你会有类似的东西:
<serviceBehaviors>
<behavior name="myBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior
</serviceBehaviors>
...
<services>
<service name="NamespaceQualifiedServiceClass" behavior="myBehavior" >
<endpoint address="https://www.sslloadbalancer.com" binding="someBinding" contract="IMyServiceInterface" listenUri="http://www.servicehost.com" ... />
</service>
</services>
我不确定这是否适用于邮件安全性或传输安全性。对于此特定应用程序,凭据作为DataContract的一部分传递,因此我们有basicHttpBinding安全模式= none。由于传输是安全的(对ssl负载均衡器)没有安全问题。
也可以将listenUri属性留空,但必须存在。
不幸的是,WCF中存在一个错误,其中WSDL中导入的模式的基地址具有listenUri基地址而不是公共基地址(使用端点的地址属性配置的地址)。要解决该问题,您需要创建一个IWsdlExportExtension实现,它将导入的模式直接引入WSDL文档并删除导入。 http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf 提供了一个示例。 。此外,您可以让示例类继承BehaviorExtensionElement并使用以下命令完成两个新方法:
Public Overrides ReadOnly Property BehaviorType() As System.Type
Get
Return GetType(InlineXsdInWsdlBehavior)
End Get
End Property
Protected Overrides Function CreateBehavior() As Object
Return New InlineXsdInWsdlBehavior()
End Function
这将允许您在.config文件中添加扩展行为,并使用配置添加行为,而不必创建服务工厂。
在system.servicemodel配置元素下添加:
<endpointBehaviors>
<behavior name="SSLLoadBalancerBehavior">
<flattenXsdImports/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!--The full assembly name must be specified in the type attribute as of WCF 3.5sp1-->
<add name="flattenXsdImports" type="Org.ServiceModel.Description.FlattenXsdImportsEndpointBehavior, Org.ServiceModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
然后使用behaviorConfiguration属性
引用端点配置中的新端点行为<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">