2009-03-11 14 views
9

Tenemos un servicio WCF alojado en ServerA, que es un servidor con acceso a Internet no directo y tiene una dirección IP enrutable que no es de Internet.WCF, metadatos y BIGIP: ¿Puedo forzar la URL correcta para los elementos WSDL?

El servicio está liderado por BIGIP que maneja el cifrado y descifrado SSL y reenvía la solicitud no cifrada a ServerA (actualmente NO realiza ningún equilibrio de carga, pero es probable que se agregue en el futuro) en un específico Puerto.

Lo que eso significa es que nuestros clientes llamarían al servicio a través del https://www.OurDomain.com/ServiceUrl y se pondrían a nuestro servicio en http://SeverA:85/ServiceUrl a través del dispositivo BIGIP;

Cuando navegamos a la WSDL publicado el https://www.OurDomain.com/ServiceUrl todas las direcciones contenidas en el WSDL se basan en la dirección de http://SeverA:85/ServiceUrl base de

Nos dimos cuenta de que podíamos utilizar los encabezados de host configuración para establecer el dominio, pero nuestro problema es que si bien esto resolvería el dominio, aún estaríamos usando el esquema incorrecto, usaría http://www.OurDomain.com/ServiceUrl mientras que necesitamos que sea Https.

Además, como tenemos otros servicios (basados ​​en asmx) alojados en ese servidor, tuvimos algunos problemas al configurar los encabezados del host, por lo que pensamos que podíamos lograr crear otro sitio en el servidor (usando, por ejemplo, el puerto 82) y establecer el encabezado de host en eso; ahora, además del problema http/https tenemos un problema ya que WSDL contiene el número de puerto en todas las direcciones URL, donde BigIP funciona en el puerto 443 (para SSL)

¿Existe una solución más flexible que implementar Host? Encabezados? Idealmente, necesitamos conservar la flexibilidad y la facilidad de compatibilidad.

Gracias por cualquier ayuda ...

+0

Yossi, tiene que quizás recibió una respuesta a esta de alguna parte ¿más? - (John Saunders que hizo su tarea de Oslo recientemente). –

Respuesta

6

Esto es esencialmente un problema de varias partes que implica una serie de soluciones discretas para proporcionar la respuesta completa. Básicamente hay 3 problemas para sentarse detrás del F5.

  1. El nombre del host del servicio anunciado.
  2. Nombre de host de los enlaces a xsd: esquemas importados que describen el contrato de datos
  3. el problema http/https que describe.

Cambiando los encabezados de host, como ha encontrado, resuelve 1 y 2 (puede abordar esto de formas distintas a los encabezados de host, pero no es necesario entrar aquí). El número 3 es un poco más complicado y requiere más código (demasiado para descargar aquí).

La respuesta breve es que debe escribir un ContractBehavior que implemente tanto IContractBehavior como IWsdlExportExtension.

El bit importante que necesita implementar es IWsdlExportExtension.ExportEndpoint. Dentro de este método necesita iterar sobre todas las Extensiones WsdlPort, y cuando encuentre una extensión que sea de tipo SoapAddressBinding, deberá reemplazar la propiedad SoapAddressBinding.Location con un nuevo Uri que contenga el especificador de protocolo https. También necesita hacer bits similares para las direcciones de importación xsd y los enlaces de esquema.

Si su servicio también usa WS-Addressing, entonces necesita hacer algo similar para manejar las direcciones adicionales que escribe en el wsdl.

Basé el código que terminé escribiendo en el proyecto WsdlExtras disponible en CodePlex (http://www.codeplex.com/WCFExtras/). El método utilizado en el WsdlExtras proporciona una gran base para cualquier bit adicional que necesite agregarle (De memoria, no creo que trate con los bits de WS-Addressing). El bit que desea ver es "Anular dirección URL de ubicación de SOAP".

+0

Gracias Mark, esto es más o menos lo que hemos terminado, pero no estoy seguro si mi solución es lo suficientemente completa (creo que lo es), estará realmente interesada en compararla con la suya, con suerte en algún momento de esta semana:) –

0

Si va a añadir SSL en la parte superior de servicio existente, es probable que también afectan el modo de seguridad de la unión para el cliente WCF, que se puede reemplazar fácilmente.

Para WSDL, ¿por qué no acaba de descargar los archivos, cambiar la URL a lo que desee y publicarlos manualmente como archivos?

0

Obtuve un gran consejo que al establecer el atributo de dirección en el punto final de la url que desea mostrar en el WSDL y luego agregar un atributo listenUri al punto final con el Uri real para escuchar, se lograría el truco.

la URL de la página de prueba no se vea afectado (es decir, se seguirá mostrando la dirección especificada en el ListenUri) pero dentro del WSDL se establecerá el URI correcto (la especificada en la dirección.

mayoría molesto, sin embargo, cuando probé esto poco después de haber publicado la pregunta, no pude lograr que funcionara en IIS, solo cuando me autohospejo en una aplicación de consola, al verificarme hoy encontré que sí funciona, así que ahora estoy no estoy seguro de por qué no funcionó para mí antes;

Lo que hemos hecho mientras tanto se construye un simple comportamiento personalizado que cambió la descripción del servicio poniendo la dirección requerida en el WSDL de la configuración; obv En serio, si hay un apoyo integrado para eso, es mucho mejor, así que con algo de suerte tendré algo de tiempo la próxima semana para analizar esto más a fondo.

0

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: // .. ...

En el web.config del host de servicio, el elemento de extremo 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

Gracias a Mark Allanson, que tenía exactamente el mismo escenario que yossi dahan tenía, el archivo WCFExtras.dll funcionó para mí,

step1. descargue WCFExtras.dll (http://www.codeplex.com/WCFExtras/).
step2. agregue su referencia a su proyecto.
paso3. no pierdas el tiempo escribiendo ningún código como se sugiere en la aplicación de servidor de muestra.
paso4. abrir el web.config y poner el código de abajo:

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


paso 5. También es importante tener en cuenta que si agrega una referencia mediante este URL "https://sslLoadBalancer/ServiceName.svc", entonces no funcionará, siempre recuerde agregar una referencia como: "https://sslLoadBalancer/ServiceName.svc?wsdl", de esta manera podrá agregar una referencia a su aplicación.

Eso es todo ... si todavía no funciona, entonces hágamelo saber, voy a pegar el archivo web.config completa ..

Gracias

Cuestiones relacionadas