2012-03-13 25 views
14

Piszę usługę WCF wymaga podszywania się i sesji.
Wiązanie protokołu NetTCP Nie powiodło się negocjowanie zabezpieczeń Soap

Jest ok, gdy próbowałem zadzwonić na moim komputerze lokalnym, ale na komputerze zdalnym zawsze nie powiodło się z takim błędem:

Security Support Provider Interface (SSPI) authentication failed. The server may not be running in an account with identity 'host/hostname'. If the server is running in a service account (Network Service for example), specify the account's ServicePrincipalName as the identity in the EndpointAddress for the server. If the server is running in a user account, specify the account's UserPrincipalName as the identity in the EndpointAddress for the server.

Gdybym dostarczył UPN, rzuca tożsamość udało wyjątek .

Oto mój config:

Server Config (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> 

Każda pomoc będzie mile widziana.

Odpowiedz

19

Usługi systemu Windows rejestrują się przy użyciu głównej nazwy użytkownika lub głównej nazwy usługi (documentation). Aby zacytować z tego linku: "Jeśli usługa działa pod kontem LocalSystem, LocalService lub NetworkService, nazwa główna usługi (SPN) jest generowana domyślnie w postaci hosta/ponieważ te konta mają dostęp do danych SPN komputera Jeśli usługa działa pod innym kontem, Windows Communication Foundation (WCF) generuje numer UPN w postaci @. "W rzeczywistości ten cytat jest raczej podobny do tego, o czym mówi Twój komunikat o błędzie. Wygląda więc na to, że ...

a), jeśli usługa jest uruchomiona w ramach konta Usługa lokalna lub podobnym koncie standardowym, to trzeba dostosować swój plik konfiguracyjny klienta mieć to, gdzie nazwa rzeczywistym serwerem jest " adres”, a punktem końcowym jest uruchomiony na porcie 4503:

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

b) naprzemiennie, jeśli działa na koncie profesjonalne usługi (nazwijmy go«konto_usługi»w domenie«mydomain»), a następnie chcesz

<identity> 
    <userPrincipalName value="[email protected]" /> 
</identity> 

Należy pamiętać, że może być konieczne użycie w pełni kwalifikowanej nazwy domeny w obu przypadkach, w tym na poziomie lasu i drzewa. Dla prostej domeny w twojej prywatnej sieci LAN/WAN będzie to adres address.MyDomain.local i [email protected] Jeśli twoja domena znajduje się w drzewie o nazwie MyTree, będzie to [email protected]; jeśli znajduje się w lesie o nazwie MyForest, będzie to [email protected] (i podobne dla ServicePrincipalName). W pełni kwalifikowana nazwa jest potrzebna do uwierzytelnienia when you are using Kerberos.

+1

To się zgadza. Dodam również, że podczas korzystania z usług internetowych obsługiwanych przez usługi IIS tożsamość powinna być zgodna z tożsamością puli aplikacji, z której usługa korzysta. Zostało to zmienione w niektórych wersjach IIS (może 7?) Z NetworkService (gdzie używałbyś zasady użytkownika 'NetworkService @ MACHINE-NAME') do AppPoolIdentity (gdzie używałbyś zasady usługi' host/MACHINE-NAME'). – qJake

6

Jest też brudny hack, jak pisał here, here i here, i analizowane here.

Możesz dostarczyć fałszywą nazwę główną usługi (SPN). W takim przypadku WCF nie zawiedzie, , ale powróci do NTLM w celu uwierzytelnienia, które nie weryfikuje zleceniodawcy.

Więc konfiguracja:

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

i programowo

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

użyciu ChannelFactory:

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

będzie również działać.