WCF: случайное отклонение учетных данных клиента

#c# #wcf

#c# #wcf

Вопрос:

В настоящее время мы переносим службы старого приложения WCF на серверы в новом домене. С момента миграции время от времени возникает упомянутая ниже ошибка.

Произошло исключение…

Сведения об исключении: сервер отклонил учетные данные клиента.

Система.ServiceModel.Исключение FaultException`1[System.ServiceModel.ExceptionDetail]: сервер отклонил учетные данные клиента. (Информация об ошибке равна ExceptionDetail, вероятно, созданной IncludeExceptionDetailInFaults=true , значение которого равно:

Система.ServiceModel.Безопасность.Исключение SecurityNegotiationException: сервер отклонил учетные данные клиента.

Система.Безопасность.Аутентификация.Исключение InvalidCredentialException: сервер отклонил учетные данные клиента.

Система.ComponentModel.Win32Exception: попытка входа в систему завершилась неудачно — Конец внутренней трассировки стека исключений —

в System.Net.Security.NegoState.ProcessReceivedBlob(сообщение Byte[], LazyAsyncResult lazyResult)
в System.Net.Security.NegoState.StartSendBlob(сообщение Byte[], LazyAsyncResult lazyResult)
в System.Net.Security.NegoState.StartSendBlob(сообщение Byte[], LazyAsyncResult lazyResult)
в System.Net.Security.NegoState.Проверка подлинности процесса (LazyAsyncResult lazyResult)
в System.Net.Security.NegotiateStream.Аутентифицируйте клиента (учетные данные NetworkCredential, строковое целевое имя, требуемый уровень защиты, разрешенный уровень токенизации)
на …).

Сложность в том, что все вызовы выполняются в 95% случаев, и нет прозрачной причины внезапного сбоя вызова.

Конфигурации и вызовы выглядят следующим образом:

Вызывающий:

 <binding name="Binding_ServiceTCP" 
         closeTimeout="00:30:00" openTimeout="00:30:00" 
         receiveTimeout="infinite" sendTimeout="infinite" 
         transferMode="Buffered" maxBufferSize="2147483647" 
         maxReceivedMessageSize="2147483647">
   <security mode="Transport">
       <transport clientCredentialType="Windows" />
   </security>
   <readerQuotas maxDepth="2147483647" maxArrayLength="2147483647" 
                 maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"  
                 maxStringContentLength="2147483647" />
</binding>

<Channel ChannelType="IWcfInterface" Name="ServiceName" 
         Binding="Binding_ServiceTCP" Address="net.tcp://serverinnewdomain:59886/Service" Identity="" />
  
 objectOfIWcfInterfaceImplementingClass.WcfCall();
  

Получатель:

 <service behaviorConfiguration="BehaviourName" name="ServiceName">
    <endpoint address="" binding="netTcpBinding" bindingConfiguration="Binding_ServiceTCP" contract="IWcfInterface" />
    <host>
        <baseAddresses>
            <add baseAddress="net.tcp://serverinnewdomain:59886/Service" />
        </baseAddresses>
    </host>
</service>
  
<behavior name="BehaviourName">
    <serviceMetadata httpGetEnabled="false" />
    <serviceDebug includeExceptionDetailInFaults="true" />
    <dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
  
<binding name="Binding_ServiceTCP" 
         closeTimeout="00:30:00" openTimeout="00:30:00" 
         receiveTimeout="infinite" sendTimeout="infinite" 
         transferMode="Buffered" maxBufferSize="2147483647" 
         maxReceivedMessageSize="2147483647">
    <security mode="Transport">
        <transport clientCredentialType="Windows" />
    </security>
    <readerQuotas maxDepth="2147483647" maxArrayLength="2147483647" 
                  maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" 
                  maxStringContentLength="2147483647" />
</binding>
  
 [ServiceContract(Namespace = "http://some.cool/namespace")]
[XmlSerializerFormat]
public interface IWcfInterface
{
    [OperationContract]
    [XmlSerializerFormat(SupportFaults = true)]
    SomeClass WcfCall();
}
  

Реализация зарегистрирована через замок.

 container.Register(Component.For<IWcfInterface>().ImplementedBy<WcfClass>().LifeStyle.PerWcfOperation());
  

на старых серверах установлена .NET 4.7, на новых — 4.8.

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

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

Ответ №1:

Во многом это связано с несоответствием домена Windows, и есть два решения:

  1. Поместите сервер приложений и клиент в один и тот же домен Windows.

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

Обратите внимание, что если вы используете проверку подлинности Windows, клиентский домен и сервер должны находиться в одном домене Windows.

Другое решение — не использовать проверку подлинности Windows:

 <bindings>
  <netTcpBinding>
    <binding name="TcpBinding">
      <security mode="None"></security>
    </binding>
  </netTcpBinding>
</bindings>
  

Комментарии:

1. Режим безопасности = «Нет» для одного конкретного канала спасает положение! Спасибо миллион