2008-11-08 63 views
8

¿Cómo puedo servir correctamente WSDL de un servicio web WCF ubicado en una LAN privada desde detrás de un proxy inverso que escucha IP pública?WCF Servicio web detrás del proxy inverso público

Tengo un servidor web Apache configurado en modo proxy inverso que escucha las solicitudes en una dirección IP pública y las sirve desde el host IIS interno. El servicio web WCF genera WSDL utilizando la dirección FQDN del host LAN que, por supuesto, no puede ser leída por un cliente del servicio web de Internet.

¿Existe alguna configuración que se pueda configurar en wcf application web.config o en IIS para personalizar el WSDL generado que contiene la dirección de host y poner dirección pública en su lugar?

Respuesta

9

a su clase de servicio de añadir el atributo:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)> 

Esto permite que el servicio sea dirigida por el cliente como https: // ... pero el servicio a estar alojada en http : // ..... Consulte this answer para saber cómo crear una extensión para permitir que AddressFilterMode.Any se especifique a través de la configuración sin requerir atributos de código.

En la web.config del host del servicio, el elemento del punto final debe tener una URL absoluta en el atributo de dirección que es la URL pública que utilizará el cliente. En el mismo elemento de punto final, establezca el atributo listenUri en la URL absoluta en la que el servidor de servicio está escuchando. La forma en que determino cuál es el URI absoluto predeterminado que está escuchando el host es agregar una referencia de servicio en una aplicación cliente que apunta al servidor físico donde se aloja el servicio. El web.config del cliente tendrá una dirección para el servicio. Luego copio eso en el atributo listenUri en los hosts web.config.

En la configuración de su comportamiento en servicio añadir el elemento con el atributo serviceMetaData httpGetEnabled = true

Por lo que usted tiene algo así como:

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

No estoy seguro de si esto funciona con la seguridad de los mensajes o la seguridad del transporte . Para esta aplicación en particular, las credenciales se pasaron como parte del DataContract, por lo que tuvimos basicHttpBinding security mode = none. Como el transporte es seguro (para el equilibrador de carga ssl) no hubo problemas de seguridad.

También es posible dejar en blanco el atributo listenUri, sin embargo, debe estar presente.

Desafortunadamente, hay un error en WCF donde la dirección base de los esquemas importados en el WSDL tiene la dirección base listenUri en lugar de la dirección base pública (la configurada usando el atributo de dirección del punto final). Para evitar este problema, debe crear una implementación IWsdlExportExtension que traiga los esquemas importados al documento WSDL directamente y elimine las importaciones. Un ejemplo de esto se proporciona aquí http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf.Además, puede tener la hereda ejemplo de la clase de BehaviorExtensionElement y completar los dos nuevos métodos con:

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 

Esto le permitirá añadir un comportamiento de extensión en el archivo .config y agregar el comportamiento mediante la configuración en lugar de tener que crear una fábrica de servicios.

bajo el elemento de configuración System.ServiceModel añadir:

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

y luego hacer referencia el nuevo comportamiento de punto final en su configuración de punto final mediante el atributo behaviorConfiguration

<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior"> 
+1

Solo quiero señalar que esta respuesta se basa en WCF 3.5. No he tenido la oportunidad de examinar si WCF 4.0 corrige algunos de estos problemas. Sé que se realizaron algunas mejoras para respaldar mejor los escenarios de proxy inverso. –

+0

He intentado esto y funciona, pero tiene algunos problemas: tendrás que poner todos tus tipos, contratos y enlaces en el mismo espacio de nombres y si tienes tipos nombrados como FooRequest deberás cambiarles el nombre porque wcf generará un tipo con el mismo nombre. Para mí fue más conveniente editar manualmente los archivos wsdl, de lo contrario, los usuarios de mi servicio tendrían que haber cambiado su código. –

+0

@Dutch: mi solución generalmente tendrá un proyecto de objeto comercial y un proyecto de servicio, cada uno con diferentes espacios de nombres (por ejemplo, org.app.bo y org.app.servicemodel). Los datos de los objetos comerciales se copian en objetos de servicio y viceversa. Utilizo interfaces definidas en el proyecto de servicio para definir los contratos (org.app.servicemodel.ISomeService). Los métodos de servicio generalmente toman un tipo org.app.servicemodel.SomethingRequest como parámetro y devuelven un tipo org.app.servicemodel.SomethingResponse. No he encontrado conflictos de nombres usando este tipo de configuración. ¿Estás haciendo algo más? –

Cuestiones relacionadas