WCF WebService / IIS Hosting и проблема конфигурации за брандмауэром - PullRequest
27 голосов
/ 27 апреля 2009

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

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

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

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

У меня был некоторый успех с изменением параметра в IIS с «Все неназначенные» -> «10.10.20.100»

Это заставляет Сервис генерировать свой WSDL с URI

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

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

Так что, если я изменю IP-адрес веб-сайта IIS по умолчанию с «Все неназначенные» -> «1.2.3.4», как я сделал для внутреннего адреса, то служба WCF просто вернется с ...

Неверный запрос (неверное имя хоста)

И если я оставлю IIS Configured на внутреннем 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 генерировать свои URI WSDL с внешним IP-адресом, который явно не настроен на сервере?

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

Ответы [ 6 ]

8 голосов
/ 30 апреля 2009

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

Дайте мне знать, если вы не знаете, как это сделать.

1 голос
/ 19 мая 2012

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

1 голос
/ 21 октября 2011

Несмотря на то, что это старый поток, он фактически помог мне перенести проект из 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-адрес, но, по крайней мере, я знаю, как получить вокруг него.

1 голос
/ 11 апреля 2011

Вот как вы меняете заголовок в 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 голос
/ 30 апреля 2009

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

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

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

1 голос
/ 29 апреля 2009

Я мог бы предотвратить насилие ниндзя ... если я понимаю твою проблему ... Вы можете вручную указать полный адрес, который служба должна использовать в 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" %>
...