Сбой согласования безопасности NetPCP для Soap - PullRequest
16 голосов
/ 13 марта 2012

Я пишу службу WCF, требующую олицетворения и сеанса.

Это нормально, когда я пытался вызвать его на моей локальной машине, но на удаленной машине он всегда терпел неудачу с такой ошибкой:

Ошибка аутентификации интерфейса поставщика поддержки безопасности (SSPI). Сервер может не работать в учетной записи с идентификатором «хост / имя хоста». Если сервер работает в учетной записи службы (например, «Сетевая служба»), укажите ServicePrincipalName учетной записи в качестве идентификатора в EndpointAddress для сервера. Если сервер работает под учетной записью пользователя, укажите UserPrincipalName учетной записи в качестве идентификатора в EndpointAddress для сервера.

Если я предоставил upn, он генерирует исключение из-за ошибки идентификации.

Вот мой конфиг:

Конфигурация сервера (APP):

<system.serviceModel>    
    <behaviors>
      <serviceBehaviors>
        <behavior name="default">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceAuthorization impersonateCallerForAllOperations="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="DataService.netTcpBinding">
          <readerQuotas maxArrayLength="65535" maxBytesPerRead="2147483647" maxStringContentLength="2147483647"/>
          <reliableSession enabled="true" inactivityTimeout="24:00:00" ordered="true"/>          
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="Windows" />
            <transport clientCredentialType="Windows"/>          
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
    <services>
      <service behaviorConfiguration="default" name="DataService.DataService">
        <endpoint address="" binding="netTcpBinding" bindingConfiguration="DataService.netTcpBinding" 
          name="DataService.DataService" contract="DataService.IDataService"/>
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://address:4504/"/>
            <add baseAddress="net.tcp://address:4503/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
</system.serviceModel>

Client Config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>     
        <bindings>
            <netTcpBinding>
                <binding name="DataService.DataService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                    hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                    maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
                    maxReceivedMessageSize="65536">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="24.00:00:00"
                        enabled="true" />
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                        <message clientCredentialType="Windows" algorithmSuite="Default" />
                    </security>
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://address:4503/" binding="netTcpBinding"
                bindingConfiguration="DataService.DataService"
                contract="ataService.IDataService" name="DataService.DataService">
              <identity>
                <dns value="DOMAIN"/>                                                  
              </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

22 голосов
/ 31 мая 2013

Службы Windows регистрируются либо с именем участника-пользователя, либо с именем участника-службы ( документация ).Процитируем по этой ссылке: « Если служба работает под учетной записью LocalSystem, LocalService или NetworkService, имя участника службы (SPN) создается по умолчанию в форме хоста /, поскольку эти учетные записи имеют доступ к компьютеру.Данные SPN. Если служба работает под другой учетной записью, Windows Communication Foundation (WCF) генерирует UPN в виде @."На самом деле эта цитата довольно похожа на то, что говорится в сообщении об ошибке.Таким образом, кажется, что ...

a) если служба работает под учетной записью локальной службы или аналогичной стандартной учетной записью, то вам необходимо настроить файл конфигурации client , чтобы это было, гдефактическое имя сервера - «адрес», и конечная точка работает на порту 4503:

<identity>
     <servicePrincipalName value="host/address:4503" />
</identity>

b) поочередно, если вы работаете под выделенной учетной записью службы (назовем ее «ServiceAccount» в домене »MyDomain "), тогда вы хотите

<identity>
     <userPrincipalName value="ServiceAccount@MyDomain" />
</identity>

Обратите внимание, что вам может понадобиться использовать полное доменное имя в обоих случаях, включая уровни Forest и Tree.Для простого домена внутри вашей частной LAN / WAN это будет означать address.MyDomain.local и ServiceAccount@MyDomain.local.Если ваш домен находится в дереве с именем MyTree, то это будет ServiceAccount@MyDomain.MyTree.local;если он находится в лесу с именем MyForest, то это будет Serviceaccount@MyDomain.MyTree.MyForest.local (и аналогично для ServicePrincipalName).Полное имя необходимо , когда вы используете Kerberos для аутентификации.

8 голосов
/ 08 ноября 2013

Существует также грязный хак, как написано здесь , здесь и здесь , и проанализировал здесь .

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

Итак, конфигурация:

    <identity>
      <servicePrincipalName value="dummy" >
    </identity>

и программно

    EndpointIdentity identity = EndpointIdentity.CreateSpnIdentity("dummy");

с использованием ChannelFactory:

    Uri uri = new Uri("net.tcp://<myServer>:<myPort>/myServiceAddress");
    ChannelFactory channelFactory = new ChannelFactory<IMyContract>(new NetTcpBinding());
    channelFactory.CreateChannel(new EndpointAddress(uri, identity)

тоже будет работать.

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