WCF, метаданные и BIGIP - могу ли я указать правильный URL для элементов WSDL? - PullRequest
9 голосов
/ 11 марта 2009

У нас есть служба WCF, размещенная на сервере ServerA, который является сервером без прямого доступа в Интернет и имеет маршрутизируемый IP-адрес, не связанный с Интернетом.

Служба обслуживается BIGIP, который обрабатывает SSL-шифрование и дешифрование и перенаправляет незашифрованный запрос на ServerA (в настоящий момент он НЕ выполняет никакой балансировки нагрузки, но, вероятно, будет добавлен в будущем) на конкретный порт. .

Это означает, что наши клиенты будут вызывать услугу через https://www.OurDomain.com/ServiceUrl и получать доступ к нашему сервису по http://SeverA:85/ServiceUrl через устройство BIGIP;

Когда мы просматриваем WSDL, опубликованный в https://www.OurDomain.com/ServiceUrl, все адреса, содержащиеся в WSDL, основаны на http://SeverA:85/ServiceUrl базовом адресе

Мы выяснили, что мы могли бы использовать настройку заголовков хоста для установки домена, но наша проблема в том, что, хотя это приведет к сортировке домена, мы все равно будем использовать неправильную схему - она ​​будет использовать http://www.OurDomain.com/ServiceUrl пока нам нужно чтобы это был https.

Кроме того - поскольку у нас есть другие службы (на основе asmx), размещенные на этом сервере, у нас возникли некоторые проблемы с настройкой заголовков хостов, и поэтому мы подумали, что сможем избежать создания другого сайта на сервере (например, используя порт 82) и установите заголовок хоста на это; Теперь, помимо проблемы http / https, у нас есть проблема, поскольку WSDL содержит номер порта во всех URL-адресах, где BigIP работает через порт 443 (для SSL)

Есть ли более гибкое решение, чем реализация Host Headers? В идеале нам нужно сохранить гибкость и простоту поддержки.

Спасибо за любую помощь ...

Ответы [ 5 ]

6 голосов
/ 17 апреля 2009

По сути, это проблема, состоящая из нескольких частей, которая включает в себя ряд отдельных решений, чтобы дать полный ответ. По сути, есть 3 проблемы с сидением за F5.

  1. Объявленное имя хоста конечной точки службы.
  2. Имя хоста ссылок на схемы xsd: import, которые описывают контракт данных
  3. описанная вами проблема http / https.

Изменение заголовков хоста, как вы нашли, решает 1 и 2 (вы можете подойти к этому другими способами, кроме заголовков хоста, но здесь нет необходимости углубляться в это). Номер 3 немного сложнее и требует больше кода (слишком много, чтобы вывести его сюда).

Краткий ответ: вам нужно написать ContractBehavior, который реализует как IContractBehavior, так и IWsdlExportExtension.

Важным битом, который вам нужно реализовать, является IWsdlExportExtension.ExportEndpoint. В этом методе вам нужно выполнить итерации по всем расширениям WsdlPort, а когда вы найдете расширение типа SoapAddressBinding, вам нужно заменить свойство SoapAddressBinding.Location новым Uri, содержащим спецификатор протокола https. Вам также нужно сделать аналогичные биты для адресов импорта xsd и ссылок схемы.

Если ваша служба также использует WS-адресацию, вам нужно выполнить нечто подобное для обработки дополнительных адресов, которые она записывает в wsdl.

Я основал код, который в итоге написал, на проекте WsdlExtras, доступном в CodePlex (http://wcfextras.codeplex.com/). Метод, используемый в WsdlExtras, обеспечивает отличную базу для любых дополнительных битов, которые вам, возможно, понадобится добавить в него (Из памяти не думайте, что он имеет дело с битами WS-Addressing.) Бит, который вы хотите посмотреть, это «Переопределить URL-адрес расположения SOAP».

1 голос
/ 21 ноября 2013

Благодаря Марку Аллансону у меня был точно такой же сценарий, как и у Йосси Дахана, у меня работал файл WCFExtras.dll,

step1. скачать WCFExtras.dll (http://www.codeplex.com/WCFExtras/).
шаг 2. добавить ссылку на ваш проект.
шаг 3. не тратьте свое время на написание кода, как предложено в примере приложения сервера.
step4. Откройте файл web.config и введите следующий код:

  <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. Также важно отметить, что если вы добавите ссылку по этому URL "https://sslLoadBalancer/ServiceName.svc", то она не будет работать, всегда не забывайте добавлять ссылку как: "https://sslLoadBalancer/ServiceName.svc?wsdl" таким образом, вы сможете добавить ссылку в свое приложение.

Вот и все ... если все еще не работает, дайте мне знать, я вставлю полный файл web.config ..

Спасибо

0 голосов
/ 02 июня 2009

К вашему классу обслуживания добавьте атрибут:

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>

Это позволяет клиенту обращаться к сервису в виде https: // ..., но сервис размещать на http: //.....

В файле web.config хоста службы элемент конечной точки должен иметь абсолютный URL-адрес в атрибуте адреса, который является общедоступным URL-адресом, который будет использоваться клиентом. В том же элементе конечной точки установите для атрибута listenUri абсолютный URL-адрес, который прослушивает хост службы. Способ определения абсолютного URI по умолчанию, который прослушивает хост, заключается в добавлении ссылки на службу в клиентском приложении, которая указывает на физический сервер, на котором размещена служба. У клиента web.config будет адрес службы. Затем я копирую это в атрибут listenUri в хосте web.config.

В вашей конфигурации поведения сервиса добавьте элемент serviceMetaData с атрибутом httpGetEnabled = true

Так что у вас будет что-то вроде:

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

Я не уверен, работает ли это с безопасностью сообщений или безопасностью транспорта. Для этого конкретного приложения учетные данные были переданы как часть DataContract, поэтому у нас был базовый режим безопасности HttpBinding = нет. Поскольку транспорт безопасен (для балансировщика нагрузки ssl), проблем с безопасностью не было.

Также можно оставить атрибут listenUri пустым, однако он должен присутствовать.

К сожалению, в WCF есть ошибка, когда базовый адрес импортированных схем в WSDL имеет базовый адрес listenUri, а не публичный базовый адрес (тот, который настроен с использованием атрибута address конечной точки). Чтобы обойти эту проблему, вам нужно создать реализацию IWsdlExportExtension, которая напрямую импортирует импортированные схемы в документ WSDL и удаляет импорт. Пример этого приведен здесь http://winterdom.com/2006/10/inlinexsdinwsdlwithwcf. Кроме того, вы можете получить пример класса, наследуемый от BehaviorExtensionElement, и дополнить два новых метода:

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

Это позволит вам добавить поведение расширения в файл .config и добавить поведение, используя конфигурацию, а не создавать фабрику сервисов.

в элемент конфигурации system.servicemodel добавить:

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

А затем сослаться на новое поведение конечной точки в конфигурации конечной точки с помощью атрибута поведениеConfiguration

<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">
0 голосов
/ 30 марта 2009

Я получил отличный совет, что установка атрибута адреса в конечной точке на URL-адрес, который вы хотите отобразить в WSDL, а затем добавление атрибута listenUri в конечную точку с фактическим Uri для прослушивания сделает свое дело.

URL-адрес на тестовой странице не будет затронут (т.е. он все равно покажет адрес, указанный в ListenUri), но в WSDL будет установлен правильный Uri (тот, который указан в адресе.

Самое досадное, однако - когда я попробовал это вскоре после того, как опубликовал вопрос, я не смог заставить его работать в IIS, только при самостоятельном размещении в консольном приложении; проверяя себя сегодня, я обнаружил, что это действительно работает; так что теперь я не уверен, почему это не сработало для меня раньше;

То, что мы сделали за это время, - это простое пользовательское поведение, которое изменило описание сервиса, оставив адрес, требуемый в WSDL, из конфигурации; очевидно, что если есть встроенная поддержка, то это намного лучше, так что я надеюсь, что на следующей неделе у меня будет время, чтобы разобраться в этом подробнее.

0 голосов
/ 28 марта 2009

Если вы добавляете SSL поверх существующей службы, это, вероятно, также повлияет на режим безопасности привязки для клиента WCF, который вы можете легко переопределить.

Для WSDL, почему бы вам не просто загрузить файлы, изменить URL-адрес на любой другой и опубликовать их вручную в виде файлов?

...