2010-05-06 8 views
16

Ich habe eine seltsame Situation hier. Ich habe es funktioniert, aber ich verstehe nicht warum. Situation ist wie folgt:WCF-Client-Endpunkt: SecurityNegotiationException ohne <dns>

Es gibt einen WCF-Dienst, den meine Anwendung (eine Website) aufrufen muss. Der WCF-Dienst macht eine netTcpBinding verfügbar und erfordert Transportsicherheit (Windows). Client und Server befinden sich in derselben Domäne, aber auf verschiedenen Servern.
So ein Client Ergebnis in der folgenden config (meist standardmäßig)

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

zu erzeugen, wenn ich die Website ausführen und den Aufruf an den Dienst machen, bekomme ich folgende Fehlermeldung:

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

Jetzt, wenn ich die Konfiguration des Clients nur ändern, wie so:

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

alles funktioniert und mein Server meldet glücklich, dass es durch th genannt wurde Der Dienstaccount, der den AppPool für meine Website hostet. Alles gut.

Meine Frage ist jetzt: warum funktioniert das? Was macht das? Ich kam zu dieser Lösung durch bloßes Versuch-und-Irrtum. Für mich scheint es, dass alle <dns /> Tag ist sagen, dass der Client die Standard-DNS für die Authentifizierung verwenden, aber tut es das nicht trotzdem?

UPDATE
Nach einiger mehr Forschung und Trial-and-error, ich habe immer noch keine Antwort auf dieses Problem gefunden. In einigen Fällen, wenn ich die <dns /> nicht bereitstellen, erhalte ich die Credentials rejected Fehler, aber wenn ich die <dns value="whatever"/> Config bereitstellen, funktioniert es. Warum?

+0

Solche SSPI-Probleme mit unserer Client/Service-WCF-Kommunikation hatten wir schon länger, konnten sie aber nie richtig lösen und traten nur bei einigen Benutzern auf einigen Rechnern auf. Die "DNS" Identität - auch eine leere - scheint den Tick zu machen ... einfach wow. –

Antwort

12

<dns/> Mit diesem Tag kann der Client die Serveridentität überprüfen. Wenn Sie beispielsweise <dns value="google.com"/> angeben, wird überprüft, ob der WCF-Server google.com-Identität bereitstellt. Da du <dns/> sagst, erlaubt es wahrscheinlich nur jedem, dich zu bedienen.

Mehr Infos unter Service Identity and Authentication

+0

Nun, nachdem ich diese Seite noch einmal durchgelesen habe und verschiedene Konfigurationen ausprobiert habe, ist es immer noch nicht gelöst. Selbst wenn ich 'my-crappy-unexisting-dummy-domain.com' anbiete, funktioniert es immer noch.Ich dachte, es muss versuchen, die Anfrage zu machen und dann auf einen Standard zurückfallen, aber ich kann nichts in der Protokollierung finden, die vorschlagen würde, dass der DNS-Server oder der Anwendungsserver sogar versucht, sich gegen diese Domäne zu authentifizieren ... Also meine Frage ist noch ungelöst. Danke, dass du mir geholfen hast! – RoelF

+0

Ich denke, Sie müssten ein Zertifikat mit einem Domain-Namen haben, damit sich der Client authentifizieren kann. – Vitalik

+0

+1 Hallo, kannst du das bitte für mich erklären, also was heißt das, wenn die DNS einen Wert = "localhost" hat? – Lamps

5

MSDN "Service Identity and Authentication" erklärt, dass der Endpunkt Identitätsabschnitt eine clientseitige Sicherheitsvorkehrung gegen Phishing Systeme ermöglicht.

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

MSDN Siehe auch "Service Identity Sample".

0

keine Antwort, aber der gleiche „Trick“ funktioniert, wenn Sie die EndpointAddress über Code erstellen:

// 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("")); 

Es ist seltsam, und ich weiß nicht, warum dies funktioniert, aber es scheint zu helfen.