2009-04-27 8 views
27

У меня есть простой веб-сервис WCF. Он размещен на IIS на веб-сайте по умолчанию в нашем производственном домене. (местный адрес: 10.10.20.100)WCF WebService/IIS Ошибка хостинга и конфигурации за брандмауэром

По умолчанию этот веб-сайт по умолчанию был настроен для IP-адресов «Все неназначенные» в порту 80. Однако я заметил, что это вызвало работу службы WCF с ее WSDL с использованием локального имени DNS-сервера. то есть все идентификаторы URI в WSDL были

http://myserver.subdomain.domain.com/.../... 

Это не было хорошо, как мне нужно, чтобы разоблачить эту услугу сайтов, которые не имеют знаний о производственной среде внутреннего DNS. И этот конкретный сервер не имеет внешнего DNS-имени. Просто внешний IP-адрес ...

Я имел некоторый успех с изменением параметров в IIS от «All Unassigned» -> «10.10.20.100»

Это вызывает службу генерировать это WSDL с URIs

http://10.10.20.100/.../... 

Это нормально для других машин в пределах подобласти и на других субдоменах, но именно здесь я застреваю. Внешний IP-адрес серверов (1.2.3.4) отображается через некоторый перевод NAT/PAT, поэтому он явно не настроен в настройках IP-адресов серверов (то есть он не отображается в соответствии с IP-конфигурацией)

Так что если я изменю ИСИ по умолчанию IP-сайта Адрес от «All Unassigned» -> «1.2.3.4», как я сделал для внутреннего адреса, то служба WCF просто возвращается с ...

Bad Request (Invalid Hostname)

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

No protocol binding matches the given address 
'http://1.2.3.4/TestService/Service.svc'. Protocol bindings are 
configured at the Site level in IIS or WAS configuration 

Есть ли способ сделать IIS/WCF генерировать WSDL URI с внешним IP-адресом, который явно не настроен на сервере?

Кто-нибудь мне поможет, прежде чем я сброшу службы WCF из окна.

+2

Это хороший вопрос. Почему такие вопросы не получают никаких проблем, но такие вопросы, как «Устали от программирования GUI/бизнес-приложений, что делать дальше?» получить 4 за считанные минуты? –

+0

У меня, к сожалению, нет ответа для вас, я могу предложить только возвышение. +1. –

+0

Цените ответы до сих пор ребята. Я собираюсь попробовать предложение Стива сегодня, переопределив ServiceHost, и если это не сработает, я укушу пулю и заставлю sysops получить новое FQDN для нашего API-сервера. –

ответ

8

Это потому, что у вас нет установленных заголовков. Это, кажется, очень распространенная проблема, я все время сталкиваюсь с ней. Конфигурации для uris, которые он генерирует, не существует, он ищет правильный адрес, исследуя заголовок узла сайта. Даже если он находится в виртуальном каталоге, вам нужно перейти к родительскому, в вашем случае, по умолчанию, и добавить заголовок узла.

Сообщите мне, если вы не знаете, как это сделать.

+0

У меня была такая же проблема, и это было исправлено с помощью этого решения, но я подумал, что это только привело к хостингам https. Возможно, нет. Я добавил заголовок узла, используя скрипт adsutil.vbs на сервере IIS. Он заставляет порт 443 иметь определенное имя хоста, а не значение по умолчанию. –

+0

Но я знаю, что вы можете установить заголовки узлов для небезопасных привязок, поэтому, возможно, стоит попробовать. –

+0

Как добавить заголовок узла? – Omu

1

Возможно, я смогу предотвратить насилие ниндзя ... если я понимаю вашу проблему ... Вы можете вручную указать полный адрес, который служба должна использовать в web.config, в отличие от того, чтобы ServiceHost выяснил это для тебя. Вы должны установить базовый адрес вашей службы:

<service behaviorConfiguration="Behaviour1" name="Api.Poll"> 
    <endpoint address="soap" binding="basicHttpBinding" bindingConfiguration="soapBinding" 
     contract="Api.IPoll" /> 
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
    <host> 
     <baseAddresses> 
     <add baseAddress="http://www.mydomain.com/Api" /> 
     <add baseAddress="http://10.10.20.30/Api" /> 
     </baseAddresses> 
    </host> 
    </service> 

Используя этот метод, ваш сервис должен принять базовый адрес, указанный, а также имя службы, с дополнительным адресом конечной точки, если у вас есть. Кроме того, вам необходимо будет использовать настраиваемый ServiceHostFactory для программного программирования базового адреса. Смотрите ниже:

public class ServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    {       
     ServiceHost host; 

     host = new ServiceHost(serviceType, baseAddresses[0]); 

     return host; 
    } 

Наконец, как только вы построить класс ServiceHostFactory, вы должны подключить его к службе путем редактирования разметки в SVC-файле:

<%@ ServiceHost Language="C#" Debug="true" Service="Api.Poll" Factory="Api.ServiceHostFactory" CodeBehind="Poll.svc.cs" %> 
+0

Раздел BaseAddress файла web.config полностью игнорируется при размещении в IIS. Не имеет никакого значения, если он присутствует или нет. IIS определяет адрес, основанный на конфигурации виртуального каталога. http://stackoverflow.com/questions/56249/wcf-service-configuration-file-question-regarding-baseaddresses –

+1

Хм ... Я использовал его раньше в IIS, но это был другой сценарий с несколькими базовыми адресами ,Интересно, можете ли вы использовать ServiceHostFactory для установки базового адреса программно. См. Пересмотренный ответ. – Steve

+0

Приветствия этому Стиву ... Его 9 вечера по Гринвичу здесь, поэтому я попробую, когда вернусь в офис и вернусь к вам завтра. Можете ли вы просто уточнить, где я создаю этот класс. Я просто забрасываю его в папку App_Code, а затем предоставляю ли мне эту услугу? –

1

Должен ли он быть IP-адрес, а не полное доменное имя?Заменив на полное доменное имя и установив, что в заголовки узлов для этого сайта, то привязка к нему через

cscript //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/1/ServerBindings ":80:hostname.example.com" 

затем рециркуляция приложение бассейн затем будет производить это имя хоста в сгенерированном WSDL. Вы получаете выгоду от этого - вы можете настроить внутренний DNS, который разрешает это полное доменное имя для внутреннего IP-адреса и внешний DNS, который разрешает ваш IP-адрес брандмауэра, тогда одна и та же система будет работать без каких-либо изменений.

1

Вот как вы меняете заголовок в IIS7. Также поместите мой web.config для некоторых, если это поможет.

http://www.sslshopper.com/article-ssl-host-headers-in-iis-7.html

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
    <compilation debug="true" targetFramework="4.0" />  
    <customErrors mode="Off"></customErrors> 
    </system.web> 
    <system.serviceModel> 
    <client/> 
    <services> 
     <service name="WcfService1.Service1" 
behaviorConfiguration="MyServiceTypeBehaviors"> 
     <host> 
     <baseAddresses> 
      <add baseAddress="https://pws.sjukra.is/"/>   
     </baseAddresses> 
     </host> 
     <endpoint address="https://pws.sjukra.is/Service1.svc" 
        listenUri="/" 
     binding="wsHttpBinding" 
     contract="WcfService1.IService1" 
     bindingConfiguration="myBasicHttpBindingConfig"/> 
     <endpoint contract="IMetadataExchange" 
    binding="mexHttpsBinding"     
    address="mex"/> 
     </service> 
    </services> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="myBasicHttpBindingConfig"> 
      <security mode="TransportWithMessageCredential"> 
      <transport clientCredentialType="Windows" /> 
      <message clientCredentialType="UserName"/> 
      </security> 
     </binding> 
     </wsHttpBinding> 
    </bindings> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="MyServiceTypeBehaviors"> 
      <serviceMetadata httpsGetEnabled="true"/> 
      <serviceDebug httpsHelpPageEnabled="true" includeExceptionDetailInFaults="true"/> 
      <serviceCredentials type="System.ServiceModel.Description.ServiceCredentials"> 
      <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1.Service1,WcfService1"/> 
      <serviceCertificate findValue="pws.sjukra.is" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> 
       <clientCertificate> 
        <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/> 
       </clientCertificate>    
      </serviceCredentials> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"></serviceHostingEnvironment> 
    </system.serviceModel> 
    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    </system.webServer> 
</configuration> 
1

Несмотря на то, что это старый нить он на самом деле помог мне перенести проект из VS Web Developer Express для MonoDevelop, который включал в себя службу WCF.

Веб-приложение запрошенный интерфейс JavaScript, определенный с помощью службы WCF, используя следующий URL: http://127.0.0.1:8080/path-to-service/service.svc/js, который дал мне ошибку: не обязательный Нет протокола соответствует данному адресу

Вдохновленный этой теме я был в состоянии исправить проблему, потому что работа с сервисом с localhost вместо 127.0.0.1 работала! С запросом на http://localhost:8080/path-to-service/service.svc/js у меня есть интерфейс JavaScript.

На самом деле мое приложение не использовало абсолютный URL-адрес для включения интерфейса JavaScript, однако по умолчанию при запуске приложения из MonoDevelop он будет обращаться к приложению с использованием 127.0.0.1, поэтому вызов для включения JavaScript из службы не удался.

Это все еще не идеально, так как я не смог запустить приложение из MonoDevelop с помощью localhost вместо 127.0.0.1, так как конфигурация XSP позволяет мне указывать IP-адрес, но по крайней мере я знаю, как обойти это.

0

Проблема заключается в том, что после изменения порта или ip-адреса вы запускаете перезапуск пула приложений, который используете, поскольку он все еще имеет старую информацию до тех пор, пока она не будет скопирована.

Смежные вопросы