Domanda

Abbiamo un servizio WCF ospitato su ServerA che è un server con accesso a Internet non diretto e ha un indirizzo IP instradabile non Internet.

Il servizio è supportato da BIGIP che gestisce la crittografia e la decrittografia SSL e inoltra la richiesta non crittografata a ServerA (al momento NON esegue alcun bilanciamento del carico, ma che probabilmente verrà aggiunto in futuro) su una porta specifica .

Ciò significa che i nostri clienti chiamerebbero il servizio tramite https://www.OurDomain.com/ServiceUrl e verrebbe fornito al nostro servizio su http: // SeverA: 85 / ServiceUrl tramite il dispositivo BIGIP;

Quando accediamo al WSDL pubblicato su https://www.OurDomain.com/ServiceUrl tutto gli indirizzi contenuti nel WSDL si basano sull ' http: // SeverA: 85 / ServiceUrl indirizzo base

Abbiamo capito che potevamo usare l'impostazione delle intestazioni host per impostare il dominio, ma il nostro problema è che mentre questo sistemerebbe il dominio, useremmo comunque lo schema sbagliato - userebbe http://www.OurDomain.com/ServiceUrl mentre ne abbiamo bisogno per essere Https.

Inoltre - dato che abbiamo altri servizi (basati su asmx) ospitati su quel server, abbiamo avuto dei problemi nell'impostare le intestazioni dell'host, e quindi abbiamo pensato di poter fare a meno di creare un altro sito sul server (usando, diciamo, la porta 82) e impostare l'intestazione host su quello; ora, oltre al problema http / https, abbiamo un problema in quanto WSDL contiene il numero di porta in tutti gli URL, dove BigIP funziona sulla porta 443 (per SSL)

Esiste una soluzione più flessibile dell'implementazione delle intestazioni host? Idealmente, dobbiamo mantenere la flessibilità e la facilità di supporto.

Grazie per l'aiuto ...

È stato utile?

Soluzione

Questo è essenzialmente un problema in più parti che coinvolge una serie di soluzioni discrete per fornire la risposta completa. Essenzialmente ci sono 3 problemi con il sedere dietro la F5.

  1. Nome host dell'endpoint del servizio pubblicizzato.
  2. Nome host dei collegamenti a xsd: schemi importati che descrivono il contratto dati
  3. il problema http / https che descrivi.

Cambiando le intestazioni host, come hai trovato risolve 1 e 2 (puoi affrontarlo in modi diversi dalle intestazioni host, ma non c'è bisogno di approfondire qui). Il numero 3 è un po 'più complicato e richiede più codice (troppo per scaricarlo qui).

La risposta breve è che è necessario scrivere un ContractBehavior che implementa sia IContractBehavior che IWsdlExportExtension.

Il bit importante che devi implementare è IWsdlExportExtension.ExportEndpoint. All'interno di questo metodo è necessario scorrere tutte le estensioni di WsdlPort e quando si trova un'estensione di tipo SoapAddressBinding è necessario sostituire la proprietà SoapAddressBinding.Location con un nuovo Uri che contiene l'identificatore del protocollo https. È inoltre necessario eseguire bit simili per gli indirizzi di importazione xsd e i collegamenti dello schema.

Se anche il tuo servizio utilizza WS-Addressing, devi fare qualcosa di simile per gestire gli indirizzi aggiuntivi che scrive su wsdl.

Ho basato il codice che ho finito per scrivere sul progetto WsdlExtras disponibile su CodePlex ( http: // wcfextras. codeplex.com/ ). Il metodo utilizzato in WsdlExtras fornisce un'ottima base per qualsiasi bit aggiuntivo che potrebbe essere necessario aggiungere ad esso (dalla memoria non penso che abbia a che fare con i bit WS-Addressing). Il bit che vuoi guardare è il " Sostituisci URL posizione indirizzo SOAP " ;.

Altri suggerimenti

Grazie a Mark Allanson, ho avuto esattamente lo stesso scenario di yossi dahan, il file WCFExtras.dll ha funzionato per me,

step1. scaricare WCFExtras.dll (http://www.codeplex.com/WCFExtras/) .
passo 2. aggiungi il riferimento al tuo progetto.
step3. non perdere tempo a scrivere alcun codice come suggerito nell'app del server di esempio.
step4. apri web.config e inserisci il codice seguente:

  <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. anche importante notare che se aggiungi il riferimento con questo URL " https: //sslLoadBalancer/ServiceName.svc" allora non funzionerà, ricorda sempre di aggiungere il riferimento come: " https : //sslLoadBalancer/ServiceName.svc? wsdl " in questo modo sarai in grado di aggiungere riferimenti alla tua applicazione.

Ecco ... se ancora non funziona, fammi sapere, incollerò il file web.config completo ..

Grazie

Se stai aggiungendo SSL al di sopra del servizio esistente, probabilmente influenzerebbe anche la modalità di sicurezza dell'associazione per il client WCF, che puoi facilmente ignorare.

Per WSDL, perché non scaricare semplicemente i file, cambiare l'URL come desiderato e pubblicarli manualmente come file?

Ho ricevuto un ottimo consiglio sul fatto che l'impostazione dell'attributo address sull'endpoint sull'URL che si desidera visualizzare nel WSDL e quindi aggiungere un attributo hearUri all'endpoint con l'URI effettivo su cui ascoltare farebbe il trucco.

L'URL nella pagina di test non viene interessato (ovvero mostrerà comunque l'indirizzo specificato in ListenUri) ma all'interno del WSDL verrà impostato l'Uri corretto (quello specificato nell'indirizzo.

In modo molto fastidioso, però: quando l'ho provato poco dopo aver pubblicato la domanda, non sono riuscito a farlo funzionare all'interno di IIS, solo quando l'hosting automatico in un'app console; controllandomi oggi ho scoperto che funziona davvero; quindi ora non sono sicuro del motivo per cui non ha funzionato prima per me;

Ciò che abbiamo fatto nel frattempo è stato creato un semplice comportamento personalizzato che ha cambiato la descrizione del servizio mettendo l'indirizzo richiesto nel WSDL dalla configurazione; ovviamente se c'è un supporto integrato per questo è molto meglio, quindi spero che avrò un po 'di tempo la settimana prossima per approfondire ulteriormente questo aspetto.

Alla tua classe di servizio aggiungi l'attributo:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>

Ciò consente al servizio di essere indirizzato dal client come https: // ... ma il servizio può essere ospitato su http: // .....

Nel web.config dell'host del servizio, l'elemento endpoint deve avere un URL assoluto nell'attributo address che è l'URL pubblico che verrà utilizzato dal client. Nello stesso elemento endpoint, impostare l'attributo hearUri sull'URL assoluto su cui l'host del servizio è in ascolto. Il modo in cui determino quale sia l'URI assoluto predefinito su cui l'host è in ascolto è quello di aggiungere un riferimento al servizio in un'applicazione client che punti il ??server fisico su cui è ospitato il servizio. Il web.config del client avrà un indirizzo per il servizio. Lo copio quindi nell'attributo hearUri nell'host web.config.

Nella configurazione del comportamento del servizio aggiungere l'elemento serviceMetaData con l'attributo httpGetEnabled = true

Quindi avrai qualcosa del tipo:

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

Non sono sicuro che funzioni con la sicurezza dei messaggi o dei trasporti. Per questa particolare applicazione, le credenziali sono state passate come parte di DataContract, quindi abbiamo avuto la modalità di sicurezza basicHttpBinding = none. Poiché il trasporto è sicuro (per il bilanciamento del carico ssl) non vi sono stati problemi di sicurezza.

È anche possibile lasciare vuoto l'attributo hearUri, tuttavia deve essere presente.

Sfortunatamente, c'è un bug in WCF in cui l'indirizzo di base degli schemi importati nel WSDL ha l'indirizzo di base hearUri piuttosto che l'indirizzo di base pubblico (quello configurato usando l'attributo address dell'endpoint). Per aggirare quel problema, è necessario creare un'implementazione IWsdlExportExtension che porta direttamente gli schemi importati nel documento WSDL e rimuove le importazioni. Un esempio è fornito qui http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf . Inoltre, puoi avere la classe di esempio ereditata da BehaviorExtensionElement e completare i due nuovi metodi 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

Questo ti permetterà di aggiungere un comportamento di estensione nel file .config e aggiungere il comportamento usando la configurazione piuttosto che dover creare una factory di servizio.

nell'elemento di configurazione system.servicemodel aggiungere:

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

E quindi fare riferimento al nuovo comportamento dell'endpoint nella configurazione dell'endpoint utilizzando l'attributo behaviorConfiguration

<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top