2010-05-06 13 views
16

Sto avendo una strana situazione qui. Ho funzionato, ma non capisco perché. La situazione è la seguente:Endpoint client WCF: SecurityNegotiationException senza <dns>

C'è un servizio WCF che la mia applicazione (un sito Web) deve chiamare. Il servizio WCF espone un netTcpBinding e richiede Transport Security (Windows). Il client e il server si trovano nello stesso dominio, ma su server diversi.
Così generando un risultato client nella seguente configurazione (per lo più valori predefiniti)

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
     <binding name="MyTcpEndpoint" ...>   
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
           enabled="false" /> 
      <security mode="Transport"> 
       <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/> 
       <message clientCredentialType="Windows" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="net.tcp://localhost:xxxxx/xxxx/xxx/1.0" 
        binding="netTcpBinding" bindingConfiguration="MyTcpEndpoint" 
        contract="Service.IMyService" name="TcpEndpoint"/> 
    </client> 
</system.serviceModel> 

Quando eseguo il sito ed effettuare la chiamata al servizio, ottengo il seguente errore:

System.ServiceModel.Security.SecurityNegotiationException: Either the target name is incorrect or the server has rejected the client credentials. ---> System.Security.Authentication.InvalidCredentialException: Either the target name is incorrect or the server has rejected the client credentials. ---> System.ComponentModel.Win32Exception: The logon attempt failed 
    --- End of inner exception stack trace --- 
    at System.Net.Security.NegoState.EndProcessAuthentication(IAsyncResult result) 
    at System.Net.Security.NegotiateStream.EndAuthenticateAsClient(IAsyncResult asyncResult) 
    at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.InitiateUpgradeAsyncResult.OnCompleteAuthenticateAsClient(IAsyncResult result) 
    at System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorAsyncResult.CompleteAuthenticateAsClient(IAsyncResult result) 
    --- End of inner exception stack trace --- 

Server stack trace: 
    at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result) 
    at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) 
    at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) 
.... 

Ora, se ho appena alterare la configurazione del client in questo modo:

<endpoint address="net.tcp://localhost:xxxxx/xxxx/xxx/1.0" 
       binding="netTcpBinding" bindingConfiguration="MyTcpEndpoint" 
       contract="Service.IMyService" name="TcpEndpoint"> 
     <identity> 
      <dns /> 
     </identity> 
    </endpoint> 

tutto funziona e il mio server segnala felicemente che stato chiamato da th L'account di servizio che ospita l'AppPool per il mio sito web. Tutto bene.

La mia domanda ora è: perché funziona? Cosa fa questo? Sono arrivato a questa soluzione solo per tentativi ed errori. A me sembra che tutto il tag <dns /> indichi al client di utilizzare il DNS predefinito per l'autenticazione, ma non lo fa comunque?

UPDATE
Così, dopo un po 'di ricerca e di tentativi ed errori, non ho ancora trovato una risposta a questo problema. In alcuni casi, se non fornisco lo <dns />, ottengo l'errore Credentials rejected, ma se fornisco la configurazione <dns value="whatever"/>, funziona. Perché?

+0

Avendo tali problemi SSPI con le comunicazioni WCF client/servizio per un po 'di tempo, ma non è mai stato risolto correttamente e si è verificato solo con alcuni utenti su alcune macchine. L'identità "DNS" - anche se vuota - sembra fare il segno di spunta ... solo wow. –

risposta

12

<dns/> tag consente al client di verificare l'identità del server. Ad esempio, se hai detto <dns value="google.com"/>, verificherebbe che il server WCF fornisca l'identità di google.com. Dal momento che dici <dns/> probabilmente permetti a tutti di servirti.

Maggiori informazioni presso Service Identity and Authentication

+0

Bene, dopo aver letto di nuovo quella pagina e aver provato alcune configurazioni diverse, non è ancora stato risolto. Anche se fornisco 'my-crappy-inesistente-dummy-domain.com', funziona ancora.Ho capito, deve provare a fare la richiesta e poi tornare a un valore predefinito, ma non riesco a trovare nulla nella registrazione che suggerirebbe che il server DNS o il server delle applicazioni tentassero anche di autenticare contro quel dominio ... Quindi la mia domanda è ancora non risolto. Grazie per avermi aiutato comunque! – RoelF

+0

Penso che avresti bisogno di avere un certificato con un nome di dominio in modo che il client possa autenticarsi. – Vitalik

+0

+1 Ciao, potresti spiegarmi questo per me, quindi cosa significa se il dns ha un valore = "localhost"? – Lamps

5

di MSDN "Service Identity and Authentication" spiega che la sezione endpoint identità consente una precauzione di sicurezza lato client contro gli schemi di phishing.

Da MSDN:

After the client initiates a communication to an endpoint and the service authenticates itself to the client, the client compares the endpoint identity value with the actual value the endpoint authentication process returned. If they match, the client is assured it has contacted the expected service endpoint. This functions as a protection against phishing by preventing a client from being redirected to an endpoint hosted by a malicious service.

vedere anche MSDN di "Service Identity Sample".

0

Non è una risposta, ma lo stesso "trucco" funziona se si crea l'EndpointAddress tramite il codice:

// does fail on some machines for some users 
// (I have no explanation here - just crazy) 
var address = new EndpointAddress(new Uri(url)); 

// will work and the dns entry doesn't matter 
address = new EndpointAddress(new Uri(url), UpnEndpointIdentity.CreateDnsIdentity("")); 

E 'strano e non so perché questo sta funzionando, ma sembra aiutare.