2008-11-08 10 views
8

Comment puis-je traiter correctement le WSDL d'un service Web WCF situé dans un réseau local privé derrière un proxy inverse écoutant sur IP publique? J'ai un serveur web Apache configuré en mode reverse proxy qui écoute les requêtes sur une adresse IP publique et les sert à partir de l'hôte IIS interne. Le service Web WCF génère WSDL en utilisant l'adresse FQDN de l'hôte LAN qui, bien sûr, ne peut pas être lu par un client de service Web Internet.Webservice WCF derrière un proxy inverse public

Y a-t-il des paramètres pouvant être configurés dans le fichier web.config de l'application wcf ou dans IIS afin de personnaliser l'adresse hôte contenant le WSDL généré et de mettre l'adresse publique à la place?

Répondre

9

à votre classe de service ajouter l'attribut:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)> 

Cela permet au service à traiter par le client comme https: // ... mais le service hébergé sur http : // ..... Voir this answer pour savoir comment créer une extension pour permettre à AddressFilterMode.Any d'être spécifié via la configuration sans nécessiter d'attributs de code.

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 est l'URL publique qui sera utilisée par le client. Dans le même élément de noeud final, 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 client 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 dans les hôtes web.config.

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

Ainsi, vous aurez 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 le message de sécurité ou la sécurité des transports . Pour cette application particulière, les informations d'identification ont été transmises dans le cadre du contrat DataContract, de sorte que basicHttpBinding security mode = none a été défini. Comme le transport est sécurisé (vers l'équilibreur de charge ssl), il n'y a pas eu de problèmes de sécurité.

Il est également possible de laisser l'attribut listenUri vide, mais il doit être présent. Malheureusement, il y a un bogue dans WCF où 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 en utilisant l'attribut address du point final). Pour contourner ce problème, vous devez créer une implémentation IWsdlExportExtension qui amène 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.vous pouvez avoir en outre Hériter de classe exemple 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 ajoutez le comportement en utilisant la configuration plutôt que d'avoir à créer une usine de service.

sous l'élément de configuration System.ServiceModel ajouter:

<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 puis font référence au nouveau comportement de point de terminaison dans la configuration de votre terminal en utilisant l'attribut behaviorConfiguration

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

Je veux juste noter que cette réponse est basée sur WCF 3.5. Je n'ai pas eu l'occasion d'examiner si WCF 4.0 corrige certains de ces problèmes. Je sais que certaines améliorations ont été apportées pour mieux prendre en charge les scénarios de proxy inverse. –

+0

J'ai essayé ceci et cela fonctionne, mais il a quelques problèmes: vous devrez mettre tous vos types, contrats et liaisons dans le même espace de nom et si vous avez des types nommés comme FooRequest vous devrez les renommer parce que wcf générera un type avec le même nom. Pour moi, il était plus pratique de modifier manuellement les fichiers wsdl, sinon les utilisateurs de mon service auraient dû changer leur code. –

+0

@Dutch - Ma solution comporte généralement un projet d'objet métier et un projet de service, chacun avec des espaces de noms différents (par exemple, org.app.bo et org.app.servicemodel). Les données provenant d'objets métier sont copiées dans des objets de service et vice versa. J'utilise des interfaces définies dans le projet de service pour définir les contrats (org.app.servicemodel.ISomeService). Les méthodes de service prennent généralement un paramètre org.app.servicemodel.SomethingRequest en paramètre et renvoient un type org.app.servicemodel.SomethingResponse. Je n'ai pas rencontré de conflit de noms avec ce type d'installation. Êtes-vous donig quelque chose d'autre? –

Questions connexes