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

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

  •  10-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

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

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

Это было полезно?

Решение

По сути, это задача, состоящая из нескольких частей, которая включает в себя ряд дискретных решений для получения полного ответа.По сути есть 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-адресации).Бит, на который вы хотите обратить внимание, — это «URL-адрес переопределения адреса SOAP».

Другие советы

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

шаг 1.скачайте WCFExtras.dll (http://www.codeplex.com/WCFExtras/).
шаг 2.добавьте ссылку на свой проект.
шаг 3.не тратьте время на написание кода, как это предлагается в примере серверного приложения.
шаг4.откройте 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>


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

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

Спасибо

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

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

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

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

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

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

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

<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, а не общедоступный базовый адрес (тот, который настроен с использованием атрибута адреса конечной точки). Чтобы обойти эту проблему, вам нужно создать реализацию 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">
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top