WCF Webservice зад публичен обратен прокси

Как мога правилно да обслужвам WSDL на WCF уеб услуга, намираща се в частна LAN зад обратен прокси, слушащ публичен IP?

Имам уеб сървър на Apache, конфигуриран в режим на обратен прокси, който слуша заявки на публичен IP адрес и ги обслужва от вътрешния IIS хост. WCF webservice генерира WSDL, използвайки FQDN адреса на LAN хоста, който, разбира се, не може да бъде прочетен от клиент на интернет уеб услуга.

Има ли някаква настройка, която може да бъде конфигурирана в web.config на wcf приложението или в IIS, за да персонализирате генерирания WSDL, съдържащ адрес на хост и вместо това да поставите публичен адрес?


person Robert Mircea    schedule 08.11.2008    source източник


Отговори (3)


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

<ServiceBehavior(AddressFilterMode:=AddressFilterMode.Any)>

Това позволява услугата да бъде адресирана от клиента като https://..., но услугата все още може да бъде хоствана на http://.....

Вижте моя отговор на Как да укажа AddressFilterMode.Any декларативно за това как да създадете разширение, за да позволите AddressFilterMode.Any да бъде указано чрез конфигурация, без да се изисква кодови атрибути.

В web.config на хоста на услугата елементът на крайната точка трябва да има абсолютен URL адрес в атрибута адрес, който е публичният URL адрес, който ще се използва от клиента. В същия елемент на крайна точка задайте атрибута listenUri на абсолютния URL адрес, на който хостът на услугата слуша.

Начинът, по който определям какъв е абсолютният URI по подразбиране, който хостът слуша, е да добавя препратка към услуга в клиентско приложение, което насочва физическия сървър, където се хоства услугата. Web.config на клиента ще има адрес за услугата. След това копирам това в атрибута listenUri в hosts web.config.

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

Така че ще имате нещо като това:

<serviceBehaviors>
  <behavior name="myBehavior">
    <serviceMetadata httpGetEnabled="true" />
  </behavior>
</serviceBehaviors>
<!--  ... -->
<services>
  <service name="NamespaceQualifiedServiceClass" behavior="myBehavior" >
    <endpoint listenUri="http://www.servicehost.com" 
              address="https://www.sslloadbalancer.com" 
              binding="someBinding" 
              contract="IMyServiceInterface" ... />
  </service>
</services>

Не съм сигурен дали това работи със сигурността на съобщенията или сигурността на транспорта. За това конкретно приложение идентификационните данни бяха предадени като част от DataContract, така че имахме basicHttpBindingsecuritymode=none. Тъй като транспортът е защитен (към ssl load balancer), няма проблеми със сигурността.

Възможно е също да оставите атрибута listenUri празен, но той трябва да присъства.

За съжаление има грешка в WCF, при която основният адрес на импортираните схеми в WSDL има основния адрес listenUri, а не публичния основен адрес (този, който е конфигуриран с помощта на адресния атрибут на крайната точка). За да заобиколите този проблем, трябва да създадете реализация на IWsdlExportExtension, която пренася импортираните схеми директно в WSDL документа и премахва импортиранията.

Пример за това е даден в тази статия на Вграден XSD в WSDL с WCF. Освен това можете да наследите примерния клас от 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 добавете:

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

И след това препратете новото поведение на крайната точка във вашата конфигурация на крайната точка, като използвате атрибута behaviorConfiguration

<endpoint address="" binding="basicHttpBinding" contract="WCFWsdlFlatten.IService1" behaviorConfiguration="SSLLoadBalancerBehavior">
person Richard Collette    schedule 03.06.2009
comment
Просто искам да отбележа, че този отговор е базиран на WCF 3.5. Не съм имал възможност да проверя дали WCF 4.0 коригира някои от тези проблеми. Знам, че са направени някои подобрения за по-добра поддръжка на сценарии за обратен прокси. - person Richard Collette; 02.11.2010
comment
Опитах това и работи, но има няколко проблема: ще трябва да поставите всичките си типове, договори и свързвания в едно и също пространство от имена и ако имате типове, наречени като FooRequest, ще трябва да ги преименувате, защото wcf ще генерира тип със същото име. За мен беше по-удобно да редактирам ръчно wsdl файловете, в противен случай потребителите на моята услуга ще трябва да променят кода си. - person Dutch Nico; 30.05.2011
comment
@Dutch - Моето решение обикновено ще има проект за бизнес обект и проект за услуга, всеки с различни пространства от имена (напр. org.app.bo и org.app.servicemodel). Данните от бизнес обекти се копират в обслужващи обекти и обратно. Използвам интерфейси, дефинирани в проекта за услуга, за да дефинирам договорите (org.app.servicemodel.ISomeService). Методите на услугата обикновено приемат тип org.app.servicemodel.SomethingRequest като параметър и връщат тип org.app.servicemodel.SomethingResponse. Не съм се сблъсквал с конфликти при именуване, използвайки този тип настройка. Правите ли нещо друго? - person Richard Collette; 02.06.2011
comment
Първоначално използвах отделни xml-именни пространства за моите съобщения, договор и обвързване. Всички ги поставих в едно и също пространство от имена, защото вграждането не работи. След тази промяна се натъкнах на конфликти при именуване като този: връзка - person Dutch Nico; 08.06.2011
comment
Добре, сега разбирам разликата. Добавям свои собствени версионирани пространства от имена въз основа на някои документи с най-добри практики, които съм чел. Вероятно затова не съм се сблъсквал с проблема с използването на типовете SomethingRequest и SomethingResponse. Вижте ръководство за версии blogs.msdn.com/b/craigmcmurtry /archive/2006/07/23/676104.aspx и msdn .microsoft.com/en-us/library/ms733832.aspx - person Richard Collette; 10.06.2011
comment
Грешката за импортиран WSDL с грешен базов адрес беше коригирана в .NET 3.5 SP1 и .NET 4.0. Можете да използвате следните конфигурационни елементи, за да получите правилното поведение. ‹serviceBehaviors› ‹behavior name=‹name›› ‹useRequestHeadersForMetadataAddress› ‹defaultPorts› ‹add scheme=http port=81 /› ‹add scheme=https port=444 /› ‹/defaultPorts› ‹/useRequestHeadersForMetadataAddress› ‹/поведение› ‹ /serviceBehaviors› - person Richard Collette; 10.10.2011
comment
+1 за Възможно е също да оставите атрибута listenUri празен, но той трябва да присъства. Това беше моят проблем. - person JamesQMurphy; 02.04.2015

Имам подобни проблеми, един от които беше разрешаването на публични и сървърни адреси. Това реши този проблем, въпреки че все още имам няколко проблема с удостоверяването.

Вижте: Как да промените HostName в WSDL за услуга, хоствана от IIS? от Wenlong Dong

архив

person stephenl    schedule 21.01.2009
comment

Имам ситуация, в която получавам NSDecimal и имам нужда от NSInteger. Знам, че е много малка стойност (това е абсолютно сигурно). Няма да е по-голямо от 100. Така че би било напълно добре да го прехвърлите към NSInteger, няма да се случи препълване.

Как би могло да стане това? Има само метод -doubleValue в NSDecimal.

- person Piotr Owsiak; 30.03.2010

Вижте: Задълбочено адресиране на WCF на сервизната станция от Арън Сконард

архив връзка

person Nicolas Dorier    schedule 30.12.2008
comment
Това съдържание изглежда се е преместило в msdn.microsoft.com/en-us/magazine /cc163412.aspx . - person JohnW; 09.12.2009