Проблема с аутентификацией WCF + NTLM и балансировкой нагрузки - PullRequest
0 голосов
/ 20 сентября 2011

Еще раз пытаюсь заставить мой сервис WCF работать в нашей среде с балансировкой нагрузки, и я полон надежд.Я перешел к использованию <customBinding>, поскольку кажется, что рекомендация заключается в установке директивы keepAliveEnabled.

Тем не менее, у меня возникла проблема с установкой аутентификации Windows на стороне сервера, поскольку <customBinding> не работает аналогичным образом.

На стороне сервера выглядит так:

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<bindings>
  <customBinding>
    <binding name="HttpBinding" closeTimeout="00:00:45">
      <textMessageEncoding>
        <readerQuotas maxStringContentLength="200000" maxArrayLength="200000" />
      </textMessageEncoding>
      <httpTransport keepAliveEnabled="false" maxReceivedMessageSize="200000" authenticationScheme="Negotiate"/>
    </binding>
  </customBinding>
</bindings>
<services>
    <endpoint address="http://svcserv/Services/ReportService/Reports.svc" binding="customBinding"
              bindingConfiguration="HttpBinding" contract="ReportService.IReports" >
    </endpoint>
    <endpoint address="mex" binding="customBinding" bindingConfiguration="HttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="ReportService.ReportsBehavior">
      <serviceMetadata httpGetEnabled="true"  />
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
</system.serviceModel>

На стороне клиента выглядит так:

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<bindings>
  <basicHttpBinding>
    <binding name="CustomBinding_IReports" maxReceivedMessageSize="200000">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Windows"/>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<client>
  <endpoint name="CustomBinding_IReports" address="http://omsnetdev/Services/ReportService/Reports.svc"
            binding="basicHttpBinding" bindingConfiguration="CustomBinding_IReports" contract="ReportService.IReports">
    <identity>
      <servicePrincipalName value="host/svcserv"/>
      <dns value="svcserv"/>
    </identity>
  </endpoint>
</client>
</system.serviceModel>

Если я оставлю для authenticationScheme значение «Согласовать», то яполучить что-то вроде SOAP header Action was not understood. или, в какой-то момент, Client found response content type of '', but expected 'application/soap+xml'. Если я изменю схему authenticationScheme на «Ntlm», то получаю Exception: The request failed with HTTP status 401: Unauthorized., но я считаю, что это происходит из-за сбоя согласования ( из-зазначение SPN? ), поэтому оно возвращается к «Ntlm» и завершается ошибкой.

Я бы списал это как конфигурацию на сервере IIS, но я проверил настройки.

Ответы [ 2 ]

4 голосов
/ 21 сентября 2011

Я считаю, что это не только проблема WCF, но и концептуальная модель.Вы хотите создать сценарий без сохранения состояния, но в то же время вам требуется обработка проверки подлинности с учетом состояния, поскольку NTLM (и никакая другая проверка подлинности на транспортном уровне) выполняется в рамках одного ответа на запрос.

Вот краткое описание, как работает рукопожатие:

      Client                                                Server
-----------------------------------------------------------------------------------------
Send initial request ---------------------------->
                     <----------------------------  Returns 401 with WWW-Authenticate 
                                                    header demanding NTLM
Sends empty request  ---------------------------->  
with Authorization                                
header with initial 
token                                    
                     <----------------------------  Returns 401 with WWW-Authenticate 
                                                    header containing some server token
Sends request with   ---------------------------->  
Authorization header                                
with final token                                    
                     <----------------------------  Returns 200 and expected response

Это рукопожатие должно выполняться с сервером с одинарной балансировкой нагрузки, но как только вы отключите постоянные соединения HTTP, вы заставите своего клиента открывать новыеTCP соединение для каждого звонка и каждый звонок балансируется отдельно.Это, скорее всего, закончится тем, что эти вызовы будут переданы на разные серверы => ошибка аутентификации.Короче говоря, вам нужно:

  • Балансировка нагрузки более высокого уровня, работающая поверх HTTP (аутентификация будет выполняться с балансировщиком нагрузки), и вызовы службы будут анонимными
  • Передача другого метода аутентификацииучетные данные в сообщении
  • Постоянные соединения для принудительной маршрутизации запроса на правильный сервер.Если вы размещаете службы в IIS, вы можете сократить интервал поддержки до нескольких секунд и надеяться, что это улучшит эффективность балансировки нагрузки
1 голос
/ 21 сентября 2011

Если у вас есть проблема, связанная с SPN, см. Ответ: SO WCF-Security-Problem question

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...