Pergunta

Temos um serviço WCF hospedado no servidora que é um servidor sem-direta e acesso à Internet tem um endereço IP roteáveis ??não-Internet.

O serviço é liderada por BigIP que criptografia alças SSL e descriptografia e encaminha a solicitação não criptografada para ServerA (no momento ele não realmente fazer qualquer balanceamento de carga, mas que é susceptível de ser adicionado no futuro) em uma porta específica .

O que isto significa é que os nossos clientes estaria chamando o serviço através https://www.OurDomain.com/ServiceUrl e iria começar a nosso serviço on http: // Severa: 85 / ServiceURL através do dispositivo BigIP;

Quando navegar para o WSDL publicado na https://www.OurDomain.com/ServiceUrl tudo os endereços contidos no WSDL são baseados na http: // Severa: 85 / ServiceURL endereço base

Descobrimos que poderíamos usar os cabeçalhos de host configuração para definir o domínio, mas o nosso problema é que, enquanto isso iria resolver o domínio, ainda estaríamos usando o esquema errado - usaria http://www.OurDomain.com/ServiceUrl enquanto nós precisamos que ele seja HTTPS.

Além disso - como temos outros serviços (asmx base) hospedado no servidor tivemos alguns problemas de definição os cabeçalhos de host, e então pensamos que poderia fugir com a criação de outro site no servidor (usando, por exemplo, a porta 82) e definir o cabeçalho de acolhimento em que; agora, em cima do problema http / https temos um problema como o WSDL contém o número da porta em todas as urls, onde BigIP trabalha na porta 443 (para o SSL)

Existe uma solução mais flexível do que implementar cabeçalhos de host? Idealmente, precisamos manter a flexibilidade e facilidade de suporte.

Obrigado por qualquer ajuda ...

Foi útil?

Solução

Este é essencialmente um problema multi-parte que envolve uma série de soluções discretas para fornecer a resposta completa. Basicamente, existem 3 problemas com sentado atrás da F5.

  1. O anunciado hostname terminal de serviço.
  2. Nome do host de links para XSD: import'ed esquemas que descrevem o contrato de dados
  3. o problema HTTP / HTTPS que você descreve.

Alterar os cabeçalhos de host, como você encontrou resolve 1 e 2 (você pode abordar isso em diferentes cabeçalhos de host maneiras, mas não há necessidade de entrar em detalhes aqui). Número 3 é um pouco mais complicado e requer mais código (demais para despejar aqui).

A resposta curta é que você precisa para escrever um ContractBehavior que implementa tanto IContractBehavior e IWsdlExportExtension.

O bit importante que você precisa para implementar é a IWsdlExportExtension.ExportEndpoint. Dentro deste método você precisa iterar sobre todas as extensões WsdlPort, e quando você encontrar uma extensão que é do tipo SoapAddressBinding você precisa substituir a propriedade SoapAddressBinding.Location com um novo Uri que contém o https especificador de protocolo. Você também precisa fazer pedaços semelhantes para os endereços de importação XSD e links de esquema.

Se o seu serviço também está usando WS-Addressing seguida, você precisa fazer algo semelhante para lidar com os endereços adicionais que escreve para o WSDL.

Eu baseei o código acabei escrevendo sobre os WsdlExtras projetar disponível no CodePlex ( http: // wcfextras. codeplex.com/ ). O método utilizado nos WsdlExtras fornece uma excelente base para qualquer bits extras que você pode precisar de adicionar a ele (De memória que eu não acho que ele lidou com os bits de WS-Addressing). O pouco que você quer é olhar para o "Override SABÃO Endereço Local URL".

Outras dicas

Graças à Mark Allanson, eu tinha exatamente o mesmo cenário como Yossi Dahan tive, O arquivo WCFExtras.dll trabalhou para mim,

step1. baixar o WCFExtras.dll (http://www.codeplex.com/WCFExtras/).
passo 2. adicioná-lo de referência ao seu projeto.
etapa 3. não perca seu tempo em escrever qualquer código, como sugerido no aplicativo servidor amostra.
Passo 4. abrir o web.config e colocar o código abaixo:

  <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. Também é importante observar que, se você adicionar referência por este "https://sslLoadBalancer/ServiceName.svc" URL então ele não vai trabalho, lembre-se sempre adicionar referência como: "https://sslLoadBalancer/ServiceName.svc?wsdl" Desta forma, você será capaz de adicionar referência à sua aplicação.

É isso ... se ainda não funciona, então deixe-me saber, vou colar o arquivo web.config completa ..

Graças

Se você estiver adicionando SSL no topo de serviço, ela provavelmente também afetam o modo de segurança da ligação para o cliente WCF, que você pode facilmente substituir.

Para WSDL, por que você não apenas baixar os arquivos, altere o URL para o que quiser, e publicá-las manualmente como arquivos?

Eu tenho uma ótima dica que definir o atributo de endereço no ponto de extremidade para a URL que você deseja exibir no WSDL e, em seguida, adicionar um atributo listenUri para o ponto final com o Uri real para escutar faria o truque.

O URL na página de teste não ficar afectado (isto é, ele ainda vai mostrar o endereço especificado no listenUri), mas dentro do WSDL do Uri correto será definido (o especificado no endereço.

Mais irritante, embora - quando eu tentei isso em breve depois que eu postei a pergunta, eu não poderia fazê-lo funcionar no IIS, somente quando DNS em um aplicativo do console; verificando-me hoje eu descobri que ele faz, de facto trabalho; então agora eu não sei por que não funcionou para mim antes;

O que temos feito no tempo médio é buid um comportamento personalizado simples que mudou a descrição do serviço colocando o endereço exigido no WSDL a partir configurtion; obviamente, se há suporte embutido para que é muito melhor, por isso vou hopfully obter algum tempo na próxima semana para olhar para este projecto.

Para a sua classe de serviço adicionar o atributo:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>

Isso permite que o serviço a ser abordado pelo cliente como https: // ... mas o serviço a ser hospedado em http: // .....

No web.config do serviço de acolhimento, o elemento endpoint deve ter um URL absoluto no atributo de endereço que é a URL pública que será usado pelo cliente. No mesmo elemento endpoint, defina o atributo listenUri para a URL absoluta em que o host de serviço está escutando. A forma como eu determinar que o absoluto URI padrão o anfitrião está escutando é é adicionar uma referência de serviço em um aplicativo cliente que aponta o servidor físico onde o serviço está hospedado. O web.config do cliente terá um endereço para o serviço. Eu, então, copiar que para o atributo listenUri no web.config hosts.

Na sua configuração de comportamento de serviço adicionar o elemento serviceMetadata com o atributo httpGetEnabled = true

Assim você terá algo 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>

Eu não tenho certeza se isso funciona com segurança de mensagem ou a segurança do transporte. Para esta aplicação particular, as credenciais foram aprovadas como parte do DataContract então tivemos BasicHttpBinding modo de segurança = nenhum. Uma vez que o transporte é seguro (para o balanceador de carga SSL) não houve problemas de segurança.

É também possível para deixar o atributo em branco listenUri, no entanto, deve estar presente.

Infelizmente, não é um erro no WCF onde o endereço da base de esquemas importados no WSDL tem o endereço de base listenUri em vez do endereço de base pública (o configurado usando o atributo de endereço do ponto de extremidade). Para contornar esse problema, você precisa criar uma implementação IWsdlExportExtension que traz os esquemas importados para o documento WSDL diretamente e remove as importações. Um exemplo disso é fornecido aqui http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf . Além disso, você pode ter a herdar exemplo de classe de BehaviorExtensionElement e completar os dois novos métodos com:

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

Isso permitirá que você adicionar um comportamento de extensão no arquivo config e adicionar o comportamento usando a configuração em vez de ter que criar uma fábrica de serviço.

sob o elemento de configuração System.ServiceModel add:

  <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, em seguida, fazer referência ao novo comportamento endpoint na sua configuração do endpoint usando o atributo behaviorConfiguration

<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top