wake-up-neo.net

WCF-Clientendpunkt: SecurityNegotiationException ohne <dns>

Ich habe hier eine seltsame Situation. Ich habe es funktioniert, aber ich verstehe nicht warum. Die Situation ist wie folgt: 

Es gibt einen WCF-Dienst, den meine Bewerbung (eine Website) aufrufen muss. Der WCF-Dienst macht netTcpBinding verfügbar und erfordert Transportsicherheit (Windows). Client und Server befinden sich in derselben Domäne, jedoch auf verschiedenen Servern.
Das Generieren eines Clients führt zu der folgenden Konfiguration (meistens Standardeinstellungen).

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

Wenn ich die Website starte und den Dienst anrufe, erhalte ich die 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)
....

Wenn ich jetzt einfach die Konfiguration des Clients so verändere:

    <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 er von dem Dienstkonto angerufen wurde, das den AppPool für meine Website hostet. Alles gut.

Meine Frage lautet nun: Warum funktioniert das? Was macht das? Ich bin zu dieser Lösung durch einfaches Ausprobieren gekommen. Mir scheint es, als würde das <dns />-Tag dem Client nur sagen, dass er das Standard-DNS für die Authentifizierung verwenden soll, aber tut es das überhaupt nicht?

UPDATE
Also habe ich nach einigen Nachforschungen und Versuchen noch immer keine Antwort auf dieses Problem gefunden. Wenn ich den <dns /> nicht gebe, bekomme ich in einigen Fällen die Credentials rejected Fehler, aber wenn ich die <dns value="whatever"/>config bereitstelle, funktioniert es. Warum?

18
RoelF

Mit dem <dns/>-Tag kann der Client die Serveridentität überprüfen. Wenn Sie beispielsweise <dns value="google.com"/> sagen, wird überprüft, ob der WCF-Server die Identität von google.com bereitstellt. Da Sie <dns/> sagen, erlaubt es wahrscheinlich nur jedem, Ihnen zu dienen.

Weitere Informationen unter Serviceidentität und Authentifizierung

14
Vitalik

MSDNs "Service Identity and Authentication" erläutert, dass der Endpunktidentitätsabschnitt eine clientseitige Sicherheitsvorkehrung gegen Phishing-Schemata ermöglicht.

Von MSDN: 

Nachdem der Client eine Kommunikation mit einem Endpunkt initiiert hat und der - Dienst sich gegenüber dem Client authentifiziert, vergleicht der Client den Endpunktidentitätswert Mit dem tatsächlichen Wert, den der Authentifizierungsprozess des Endpunkts Zurückgegeben hat. Wenn sie übereinstimmen, ist der Kunde versichert , Dass er den erwarteten Serviceendpunkt kontaktiert hat. Dies dient als Schutz gegen Phishing, indem verhindert wird, dass ein Client An einen Endpunkt umgeleitet wird, der von einem schädlichen Dienst gehostet wird.

Siehe auch MSDNs "Service Identity Sample" .

6
Rana Ian

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 das funktioniert, aber es scheint zu helfen.

0
Robert Muehsig