WCF WebService/IIS Хостинг и конфигурация Проблема за брандмауэром
У меня есть простой веб-сервис WCF. Он размещался на IIS на веб-сайте по умолчанию в нашем производственном домене. (локальный адрес: 10.10.20.100)
По умолчанию этот веб-сайт по умолчанию был настроен для "Все неназначенные" IP-адреса в порту 80: однако я заметил, что это вызвало службу WCF для ее создания WSDL с использованием локального имени DNS сервера. то есть все URI в wsdl были
http://myserver.subdomain.domain.com/.../...
Это было нехорошо, так как мне нужно разоблачить эту услугу на сайтах, которые не знают о внутренней среде производственной среды. И этот конкретный сервер не имеет внешнего 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 с "All Unassigned" → "1.2.3.4", как я сделал для внутреннего адреса, тогда служба WCF вернется с...
Неверный запрос (недопустимое имя хоста)
И если я покину 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 из окна.
Ответы
Ответ 1
Это потому, что у вас нет установленных заголовков хостов. Это, кажется, очень распространенная проблема, я все время сталкиваюсь с ней. Там нет конфигурации для uris, который он генерирует, он ищет правильный адрес, изучая заголовок узла сайта. Даже если это в виртуальном каталоге, вам нужно перейти к родительскому, в вашем случае, по умолчанию, и добавить заголовок узла.
Сообщите мне, если вы не знаете, как это сделать.
Ответ 2
Я мог бы предотвратить насилие ниндзя... если я понимаю вашу проблему...
Вы можете вручную указать полный адрес, который служба должна использовать в 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" %>
Ответ 3
Должен ли он быть IP-адресом, а не FQDN? Переключившись на полное доменное имя и установив это в заголовках хоста для сайта, привязка к нему через
cscript //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/1/ServerBindings ":80:hostname.example.com"
то повторная утилизация пула приложений приведет к созданию этого имени хоста в сгенерированном WSDL. Вы получаете выгоду от этого - вы можете настроить внутренний DNS, который разрешает это полное доменное имя для внутреннего IP-адреса и внешний DNS, который разрешает ваш IP-адрес брандмауэра, тогда одна и та же система будет работать без каких-либо изменений.
Ответ 4
Здесь вы можете изменить заголовок в 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>
Ответ 5
Несмотря на то, что это старый поток, он действительно помог мне перенести проект из 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-адрес, но по крайней мере я знаю, как получить вокруг него.
Ответ 6
Проблема заключается в том, что после изменения порта или ip-адреса вы запускаете перезапуск пула приложений, который вы используете, потому что он все еще имеет старую информацию до тех пор, пока она не будет скопирована.