Размещение службы WCF с использованием сети.привязка tcp в IIS 7 (недоступна извне)



Я разработал двухуровневую службу WCF и клиент Windows Winforms, которые взаимодействуют друг с другом через сеть.протокол TCP переплет.



Оба взаимодействуют и прекрасно работают в моей локальной сети, служба WCF размещается на IIS 7 на рабочей станции Windows 8.



Затем я попытался разместить службу WCF в интернете на арендованном выделенном сервере под управлением Windows server 2008 R2 с фиксированным IP-адресом: (94.23.220.199)с IIS 7 и .Net 4.5.2.



Служба WCF установлена на виртуальный путь /ScgBroadcastorService и сеть.протокол tcp был активирован. (На самом деле, все настройки IIS были сделаны точно так же, как на моем personnal IIS в моей локальной сети). Таким образом, сервис должен быть доступен извне по следующему URL: "http://94.23.220.199/ScgBroadcastorService/Service.svc ".



Если вы перейдете по этой ссылке из Вашего браузера, вы получите правильную страницу "ScgBroadcastorService Service" с двумя ссылками wsdl. (Эти ссылки правильно ссылаются на IP-адрес "94.23.220.199".



Если щелкнуть по этой ссылке, то будет правильно получен документ WSDL xml.



Таким образом, поскольку к документу wsdl можно получить доступ извне, я ожидаю, что клиент сможет связаться со службой WCF..



Но если я запускаю клиент, я получаю следующее исключение: (извините, мой домашний компьютер локализован на французском языке... Корневое исключение - " сервер отклонил учетные данные клиента.")



Вот полная след:



System.ServiceModel.Security.SecurityNegotiationException: Le serveur a rejeté les informations d'identification du client. ---> System.Security.Authentication.InvalidCredentialException: Le serveur a rejeté les informations d'identification du client. ---> System.ComponentModel.Win32Exception: La tentative d’ouverture de session a échoué
--- Fin de la trace de la pile d'exception interne ---
à System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.StartReceiveBlob(LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.CheckCompletionBeforeNextReceive(LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.CheckCompletionBeforeNextSend(Byte[] message, LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.StartReceiveBlob(LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.CheckCompletionBeforeNextReceive(LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult)
à System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult)
à System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, ChannelBinding binding, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel)
à System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel)
à System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity)
--- Fin de la trace de la pile d'exception interne ---

Server stack trace:
à System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity)
à System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream stream)
à System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator upgradeInitiator, IConnection& connection, ClientFramingDecoder decoder, IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper& timeoutHelper)
à System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)
à System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(IConnection connection, TimeoutHelper& timeoutHelper)
à System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
à System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
à System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
à System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
à System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
à System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
à System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
à System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
à System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)


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

Вот паутина.конфигурационный файл, установленный на сервере, на котором размещена служба:



<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="ScgServiceLibrary.ScgBroadcastorService">
<endpoint binding="netTcpBinding" contract="ScgServiceLibrary.IScgBroadcastorService">
<identity>
<servicePrincipalName value="host/94.23.220.199" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>


А вот конфигурационный файл клиента, который я использую извне и с хоста:



<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IScgBroadcastorService">
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://94.23.220.199/ScgBroadcastorService/Service.svc"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IScgBroadcastorService"
contract="ScgServiceLibrary.IScgBroadcastorService" name="NetTcpBinding_IScgBroadcastorService">
<identity>
<servicePrincipalName value="host/94.23.220.199" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>


Обратите внимание, что я добавил



<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />


Линия в конце паутины.конфигурационный файл на сервере, чтобы получить страница сервиса с IP-адресом на двух WSDL-ссылках. Без этой строки две ссылки включают имя компьютера "ns304385" вместо IP-адреса, и, конечно, wsdl не может быть получен извне.



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

705   4  

4 ответов:

Хорошо, я наконец-то решил проблему посреди ночи...

Мне пришлось отключить безопасность привязки nettcpbinding на обе стороны.

Но было не так просто выяснить, как отключить его на стороне сервера для контракта, требующего дуплексной связи.

Вот паутина.конфигурационный файл:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="customTcpBinding" maxReceivedMessageSize="5242880" maxConnections="10">
          <readerQuotas maxDepth="64" maxStringContentLength="5242880" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
          <security mode="None"></security>
        </binding>
      </netTcpBinding>
    </bindings>
    <services>
      <service name="ScgServiceLibrary.ScgBroadcastorService">
        <endpoint binding="netTcpBinding" bindingConfiguration="customTcpBinding" contract="ScgServiceLibrary.IScgBroadcastorService">
          <identity>
            <servicePrincipalName value="host/94.23.220.199" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
   <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
</configuration>

Хитрость заключалась в том, чтобы добавить customTcpBinding с режимом безопасности, установленным в "None" , и сослаться на эту новую привязку в конечной точке с помощью bindingConfiguration атрибут.

Не уверен, что все параметры customTcpBinding являются оптимальными, но они подходят для дуплексного контракта. (Моя первая попытка была отклонена для дуплексного контракта)

На стороне клиента мне также пришлось установить режим безопасности привязки на "None". Вот мой новый конфигурационный файл на стороне клиента:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <netTcpBinding>
                <binding name="NetTcpBinding_IScgBroadcastorService">
                    <security mode="None"></security>
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://94.23.220.199/ScgBroadcastorService/Service.svc"
                binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IScgBroadcastorService"
                contract="ScgServiceLibrary.IScgBroadcastorService" name="NetTcpBinding_IScgBroadcastorService">
                <identity>
                    <servicePrincipalName value="host/94.23.220.199" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

И, наконец, мой клиент WCF Windows WinForm прекрасно работает и взаимодействует с моей двухуровневой службой WCF !!!

Я должен сказать, что решение этой проблемы было настоящий кошмар...

Надеюсь, что это полное описание моей проблемы поможет другим разработчикам, пытающимся разместить свою дуплексную сеть.Tcp привязал службу WCF в сети и наскучил всем неожиданным исключением, прежде чем найти правильный способ изменить свои конфигурационные файлы.

Спокойной ночи, ребята ! До возвращения на работу оставалось всего три часа сна... :- (

Установка режима безопасности на " нет "- это не тот способ, которым вы должны решить эту проблему, потому что установка безопасности на " нет " также приведет к удалению конфиденциальности (шифрования) и целостности (подписи) ваших сообщений.

<security mode="None"></security>

Чтобы удалить аутентификацию, вы можете либо: 1) Установите режим безопасности в сообщение

<bindings>
    <netTcpBinding>
        <binding name="NetTcpBinding_IScgBroadcastorService">
            <security mode="Message">
                <message clientCredentialType="None" />
            </security>
        </binding>
    </netTcpBinding>
</bindings>

2) или установите режим безопасности на транспорт

<bindings>
    <netTcpBinding>
        <binding name="NetTcpBinding_IScgBroadcastorService">
            <security mode="Transport">
                <transport clientCredentialType="None" />
            </security>
        </binding>
    </netTcpBinding>
</bindings>
Должен признаться, что я не пытался проделать это с вашим кодом. Просто хочу убедиться, что люди, читающие это, знают, что аутентификация и безопасность сообщений-это не одно и то же, и они указывают в правильном направлении.

У меня была такая же ошибка для двухуровневой службы wcf, размещенной в службе windows на удаленной машине. Чтобы заставить его работать, я должен был создать входящие и исходящие правила, чтобы открыть служебный порт в расширенных настройках Брандмауэра Windows. Кроме того, я создал пользователя сервера и включил этот код в свой клиент:

this._client = new WcfService.WcfServiceClient(context);
_client.ClientCredentials.Windows.ClientCredential.UserName = user;
_client.ClientCredentials.Windows.ClientCredential.Password = password;

Вау ! Я только что нашел частичное решение !

По крайней мере, объяснение того, почему я не могу связаться со службой WCF извне !

Читаем это: https://social.msdn.microsoft.com/Forums/vstudio/en-US/1551b4e1-8e15-4da2-b155-d398379809b3/the-server-has-rejected-the-client-credentials-in-wcf?forum=wcf

Поэтому я попытался создать учетную запись на сервере с тем же именем и паролем, что и учетная запись, которую я использую на своем домашнем компьютере, когда я пытаюсь запустить клиент... и... Это работает !!!

Конечно, вы согласитесь со мной, что это неприемлемо...

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

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

Следите за новостями... Надежда скоро найдет ответ...

Comments

    Ничего не найдено.