2012-03-13 12 views
14

Sto scrivendo un servizio WCF richiede impersonate e sessione.
netTCP binding Negoziazione sicurezza sapone non riuscita

E 'ok quando ho provato a chiamarlo sulla mia macchina locale, ma sulla macchina a distanza è sempre riuscito con tale errore:

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.

Se ho fornito un UPN, getta un'identità non è riuscita un'eccezione .

Ecco la mia configurazione:

Server Config (APP): Config

<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> 

Cliente:

<?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> 

Qualsiasi aiuto sarebbe molto apprezzato.

risposta

19

I servizi Windows si registrano con un nome principale utente o un nome principale del servizio (documentation). Per quotare da tale collegamento: "Se il servizio è in esecuzione con l'account LocalSystem, LocalService o NetworkService, un nome dell'entità servizio (SPN) viene generato per impostazione predefinita nella forma di host/poiché tali account hanno accesso ai dati SPN del computer Se il servizio è in esecuzione con un account diverso, Windows Communication Foundation (WCF) genera un UPN nel formato di @. "In realtà, questa citazione è piuttosto simile a ciò che il tuo messaggio di errore sta affermando. Così sembra che ...

a) se il servizio è in esecuzione con l'account Servizio locale o simili account standard, allora avete bisogno di regolare il vostro cliente file di configurazione di avere questo, in cui il nome del server reale è " indirizzo" e il punto finale è in esecuzione sulla porta 4503:

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

b) in alternativa, se si esegue con un account di servizio dedicato (chiamiamolo 'ServiceAccount' sul dominio 'MyDomain'), poi si desidera

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

Si noti che potrebbe essere necessario utilizzare il nome di dominio completo in entrambi i casi, inclusi i livelli Foresta e Albero. Per un dominio semplice all'interno della tua LAN/WAN privata, ciò significa address.MyDomain.local e [email protected] Se il tuo dominio si trova su un albero chiamato MyTree, sarà [email protected]; se si trova in una foresta denominata MyForest, sarà [email protected] (e simile per ServicePrincipalName). Il nome completo è necessario when you are using Kerberos per l'autenticazione.

+1

Questo è corretto. Aggiungerò anche che quando si consumano servizi Web ospitati da IIS, l'identità deve corrispondere all'identità del pool di app in cui vive il servizio. Questo è stato cambiato in alcune versioni di IIS (forse 7?) Da NetworkService (dove si usa un principio utente di 'NetworkService @ MACHINE-NAME') in AppPoolIdentity (dove si usa un principio di servizio di' host/MACHINE-NAME'). – qJake

6

C'è anche un hack sporco, come pubblicato here, here, e here, e analizzato here.

È possibile fornire un nome principale di servizio fittizio (SPN). In tal caso, WCF non fallirà, ma ricadrà su NTLM per l'autenticazione che non verifica l'entità.

Quindi, la configurazione:

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

e programmaticamente

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

utilizzando ChannelFactory:

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

sarà anche funzionare.

Problemi correlati