WCF, métadonnées et BIGIP - Puis-je forcer l'URL correcte pour les éléments WSDL?

StackOverflow https://stackoverflow.com/questions/634522

  •  10-07-2019
  •  | 
  •  

Question

Nous avons un service WCF hébergé sur ServerA, qui est un serveur avec un accès Internet non direct et une adresse IP routable non Internet.

Le service est géré par BIGIP, qui gère le cryptage et le décryptage SSL et transmet la demande non cryptée à ServerA (pour le moment, il n’effectue PAS d’équilibrage de la charge, mais il est probable qu’il sera ajouté ultérieurement) sur un port spécifique. .

Cela signifie que nos clients appellent le service via https://www.OurDomain.com/ServiceUrl et accéderait à notre service via http: // SeverA: 85 / ServiceUrl via le périphérique BIGIP;

Lorsque nous parcourons le WSDL publié sur https://www.OurDomain.com/ServiceUrl tous les adresses contenues dans le WSDL sont basées sur l’adresse de base http: // SeverA: 85 / ServiceUrl

Nous avons pensé que nous pourrions utiliser le paramètre d'en-têtes d'hôte pour définir le domaine. Notre problème est que, même si cela résoudrait le domaine, nous utiliserions toujours le mauvais schéma & # 8211; il utilisera http://www.OurDomain.com/ServiceUrl pendant que nous en avons besoin.

Aussi & # 8211; Comme nous avons d'autres services (basés sur asmx) hébergés sur ce serveur, nous avons eu quelques problèmes pour paramétrer les en-têtes d'hôte. Nous avons donc pensé que nous pourrions créer un autre site sur le serveur (en utilisant, par exemple, le port 82) et définir l'en-tête d'hôte. sur ça; Maintenant, en plus du problème http / https, nous avons un problème car le WSDL contient le numéro de port dans toutes les URL, où BigIP fonctionne sur le port 443 (pour le SSL)

Existe-t-il une solution plus flexible que la mise en œuvre des en-têtes d’hôte? Idéalement, nous devons conserver souplesse et facilité de prise en charge.

Merci pour toute aide & # 8230;

Était-ce utile?

La solution

Il s'agit essentiellement d'un problème en plusieurs parties qui implique un certain nombre de solutions discrètes pour fournir une réponse complète. Il y a essentiellement 3 problèmes à s’asseoir derrière le F5.

  1. Nom d'hôte du noeud final de service publié.
  2. Nom d'hôte des liens vers xsd: schémas importés décrivant le contrat de données
  3. le problème http / https que vous décrivez.

Le fait de changer les en-têtes d’hôte, comme vous l’avez trouvé, résout les problèmes 1 et 2 (vous pouvez l’approcher autrement que par des en-têtes d’hôte, mais vous n’avez pas besoin d’entrer ici). Le numéro 3 est un peu plus compliqué et nécessite plus de code (trop pour être vidé ici).

La réponse courte est que vous devez écrire un ContractBehavior qui implémente à la fois IContractBehavior et IWsdlExportExtension.

Le bit important que vous devez implémenter est le IWsdlExportExtension.ExportEndpoint. Dans cette méthode, vous devez effectuer une itération sur toutes les extensions WsdlPort. Lorsque vous trouvez une extension de type SoapAddressBinding, vous devez remplacer la propriété SoapAddressBinding.Location par un nouvel Uri contenant le spécificateur de protocole https. Vous devez également faire des bits similaires pour les adresses d’importation xsd et les liens de schéma.

Si votre service utilise également WS-Addressing, vous devez procéder de la même manière pour gérer les adresses supplémentaires écrites dans le fichier WSDL.

J'ai basé le code que j'ai fini par écrire sur le projet WsdlExtras disponible sur CodePlex ( http: // wcfextras. codeplex.com/ ). La méthode utilisée dans WsdlExtras fournit une base idéale pour tous les bits supplémentaires que vous devrez éventuellement ajouter (De mémoire, je ne pense pas que cela concerne les bits d’adressage WS). Le bit que vous souhaitez consulter est "Remplacer l'URL de l'adresse SOAP".

Autres conseils

Merci à Mark Allanson, j'ai eu exactement le même scénario que yossi dahan, le fichier WCFExtras.dll a fonctionné pour moi,

step1. Téléchargez le fichier (http://www.codeplex.com/WCFExtras/) de WCFExtras.dll.
étape 2. ajoutez sa référence à votre projet.
étape 3. Ne perdez pas votre temps à écrire le code suggéré dans l’application Serveur exemple.
étape 4. ouvrez le fichier web.config et mettez le code ci-dessous:

  <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. Il est également important de noter que si vous ajoutez une référence à cette URL "https: //sslLoadBalancer/ServiceName.svc" ", cela ne fonctionnera pas. Pensez toujours à ajouter une référence sous la forme: & https : //sslLoadBalancer/ServiceName.svc? wsdl " Ainsi, vous pourrez ajouter une référence à votre application.

Ca y est ... si cela ne fonctionne toujours pas, faites-le-moi savoir, je vais coller le fichier complet web.config ..

Merci

Si vous ajoutez SSL au-dessus du service existant, cela affectera probablement également le mode de sécurité de la liaison pour le client WCF, que vous pouvez facilement remplacer.

Pour WSDL, pourquoi ne pas simplement télécharger les fichiers, modifier l’URL comme vous le souhaitez et les publier manuellement sous forme de fichiers?

J'ai eu un bon conseil: définir l'attribut address du noeud final sur l'URL que vous souhaitez afficher dans le WSDL, puis ajouter un attribut listenUri au noeud final avec le nom de l'URI sur lequel écouter, ce serait une bonne solution.

L'URL de la page de test n'est pas affecté (c'est-à-dire qu'il affichera l'adresse spécifiée dans ListenUri), mais dans le WSDL, le bon Uri sera défini (celui spécifié dans l'adresse.

Le plus ennuyeux, cependant - lorsque j’ai essayé cela peu après avoir posté la question, je ne pouvais pas le faire fonctionner dans IIS, mais uniquement lorsque l’auto-hébergement était hébergé dans une application de console; En me vérifiant aujourd'hui, j'ai constaté que cela fonctionnait effectivement; alors maintenant je ne sais pas pourquoi cela ne marchait pas pour moi auparavant;

Ce que nous avons fait entre-temps est un simple comportement personnalisé qui a modifié la description du service en mettant l'adresse requise dans le WSDL à partir de la configuration. évidemment, s’il existe un support intégré pour cela, c’est beaucoup mieux, je vais donc avoir un peu de temps la semaine prochaine pour approfondir cette question.

À votre classe de service, ajoutez l'attribut suivant:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>

Ceci permet au client de s’adresser au service en tant que https: // ... mais d’héberger le service sur http: // .....

.

Dans le fichier Web.config de l'hôte de service, l'élément de point de terminaison doit avoir une URL absolue dans l'attribut d'adresse qui correspond à l'URL publique qui sera utilisée par le client. Dans le même élément d'extrémité, définissez l'attribut listenUri sur l'URL absolue sur laquelle l'hôte de service écoute. La façon dont je détermine l'URI absolu par défaut que l'hôte écoute est d'ajouter une référence de service dans une application cliente qui pointe vers le serveur physique sur lequel le service est hébergé. Le web.config du client aura une adresse pour le service. Je copie ensuite cela dans l'attribut listenUri du serveur web.config.

Dans la configuration de votre comportement de service, ajoutez l'élément serviceMetaData avec l'attribut httpGetEnabled = true

Vous aurez donc quelque chose comme:

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

Je ne sais pas si cela fonctionne avec la sécurité des messages ou la sécurité du transport. Pour cette application particulière, les informations d'identification ont été transmises dans le cadre du DataContract, de sorte que nous avions le mode de sécurité basicHttpBinding = aucun. Comme le transport est sécurisé (vers l’équilibreur de charge SSL), aucun problème de sécurité n’est survenu.

Il est également possible de laisser l'attribut listenUri vide, mais il doit être présent.

Malheureusement, il existe un bogue dans WCF dans lequel l'adresse de base des schémas importés dans le WSDL a l'adresse de base listenUri plutôt que l'adresse de base publique (celle configurée à l'aide de l'attribut address du noeud final). Pour résoudre ce problème, vous devez créer une implémentation IWsdlExportExtension qui intègre directement les schémas importés dans le document WSDL et supprime les importations. Un exemple de ceci est fourni ici http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf . De plus, vous pouvez avoir la classe exemple héritée de BehaviorExtensionElement et compléter les deux nouvelles méthodes avec:

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

Cela vous permettra d'ajouter un comportement d'extension dans le fichier .config et d'ajouter le comportement à l'aide de la configuration plutôt que de créer une fabrique de services.

sous l'élément de configuration system.servicemodel, ajoutez:

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

Et référencez ensuite le nouveau comportement du terminal dans votre configuration à l'aide de l'attribut behaviorConfiguration

<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top