公共反向代理背后的 WCF Webservice

Posted

技术标签:

【中文标题】公共反向代理背后的 WCF Webservice【英文标题】:WCF Webservice behind public reverse proxy 【发布时间】:2010-09-21 11:00:26 【问题描述】:

如何从侦听公共 IP 的反向代理后面正确地提供位于专用 LAN 中的 WCF Web 服务的 WSDL?

我有一个配置为反向代理模式的 Apache 网络服务器,它侦听公共 IP 地址上的请求并从内部 IIS 主机为它们提供服务。 WCF Web 服务使用 LAN 主机的 FQDN 地址生成 WSDL,当然,互联网 Web 服务客户端无法读取该地址。

是否可以在 wcf 应用程序的 web.config 或 IIS 中配置任何设置,以自定义生成的包含主机地址的 WSDL 并放置公共地址?

【问题讨论】:

【参考方案1】:

将以下属性添加到您的服务类:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>

这允许客户端将服务寻址为https://...,但该服务仍可以托管在http://.....

请参阅我在 How to specify AddressFilterMode.Any declaratively 上的回答,了解如何创建扩展以允许通过配置指定 AddressFilterMode.Any 而无需代码属性。

在服务主机的web.config 中,端点元素必须在地址属性中有一个绝对URL,即客户端将使用的公共URL。在同一端点元素中,将listenUri 属性设置为服务主机正在侦听的绝对 URL。

我确定主机正在侦听的默认绝对 URI 的方法是在客户端应用程序中添加一个服务引用,该引用指向托管服务的物理服务器。客户端的 web.config 将包含服务的地址。然后我将其复制到主机 web.config 中的 listenUri 属性中。

在您的服务行为配置中,添加属性为httpGetEnabled=true 的元素serviceMetaData

所以你会有这样的东西:

<serviceBehaviors>
  <behavior name="myBehavior">
    <serviceMetadata httpGetEnabled="true" />
  </behavior>
</serviceBehaviors>
<!--  ... -->
<services>
  <service name="NamespaceQualifiedServiceClass" behavior="myBehavior" >
    <endpoint listenUri="http://www.servicehost.com" 
              address="https://www.sslloadbalancer.com" 
              binding="someBinding" 
              contract="IMyServiceInterface" ... />
  </service>
</services>

我不确定这是否适用于消息安全或传输安全。对于这个特定的应用程序,凭据作为 DataContract 的一部分传递,所以我们有 basicHttpBinding > security > mode=none。由于传输是安全的(对于 ssl 负载平衡器),因此不存在安全问题。

也可以将listenUri 属性留空,但它必须存在。

不幸的是,WCF 中存在一个错误,其中 WSDL 中导入架构的基地址具有 listenUri 基地址而不是公共基地址(使用端点的地址属性配置的基地址)。要解决这个问题,您需要创建一个 IWsdlExportExtension 实现,它将导入的模式直接引入 WSDL 文档并删除导入。

Inline XSD in WSDL with WCF 上的这篇文章中提供了一个示例。此外,您可以让示例类继承自 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 配置元素下添加:

<behaviors>
  <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">

【讨论】:

我只想指出,这个答案是基于 WCF 3.5。我没有机会检查 WCF 4.0 是否纠正了其中一些问题。我确实知道为了更好地支持反向代理场景,我们做了一些改进。 我已经尝试过了,它可以工作,但它有一些问题:你必须将所有类型、合同和绑定放在同一个命名空间中,如果你有类似 FooRequest 的类型'将不得不重命名它们,因为 wcf 将生成具有相同名称的类型。对我来说,手动编辑 wsdl 文件更方便,否则我的服务的用户将不得不更改他们的代码。 @Dutch - 我的解决方案通常有一个业务对象项目和一个服务项目,每个项目都有不同的命名空间(例如 org.app.bo 和 org.app.servicemodel)。来自业务对象的数据被复制到服务对象中,反之亦然。我使用服务项目中定义的接口来定义合同(org.app.servicemodel.ISomeService)。服务方法通常以 org.app.servicemodel.SomethingRequest 类型作为参数,并返回 org.app.servicemodel.SomethingResponse 类型。使用这种类型的设置我没有遇到命名冲突。你在做别的事吗? 最初我为我的消息、合同和绑定使用单独的 xml 命名空间。我都将它们放在同一个命名空间中,因为内联不起作用。在那次更改之后,我遇到了这样的命名冲突:link 好的,现在我明白了其中的区别。我根据阅读过的一些最佳实践文档添加了自己的版本化命名空间。这可能就是为什么我没有遇到使用 SomethingRequest 和 SomethingResponse 类型的问题。请参阅版本控制指南 blogs.msdn.com/b/craigmcmurtry/archive/2006/07/23/676104.aspx 和 msdn.microsoft.com/en-us/library/ms733832.aspx【参考方案2】:

我遇到了类似的问题,其中之一是公共地址和服务器地址的解析。这解决了这个问题,尽管我仍然有几个身份验证问题。

:董文龙How to change HostName in WSDL for an IIS-hosted service?

archive

【讨论】:

天哪,史蒂夫,非常感谢这个链接,过去几个小时我都快疯了。【参考方案3】:

:Service Station WCF Addressing In Depth Aaron Skonnard

archive link

【讨论】:

该内容似乎已移至msdn.microsoft.com/en-us/magazine/cc163412.aspx。

以上是关于公共反向代理背后的 WCF Webservice的主要内容,如果未能解决你的问题,请参考以下文章

Apache反向代理背后的Keycloak

反向代理背后的密钥斗篷

Nginx 反向代理背后的 Grafana 返回 alert.title

Apache 反向代理背后的 Apache Zeppelin

反向代理背后的 SOP 问题

nginx反向代理背后的grafana