Kerberos wird beim Aufrufen eines WCF-Diensts nicht verwendet

Dieser Artikel hilft Ihnen, das Problem zu beheben, bei dem Sie über NTLM anstelle von Kerberos authentifiziert werden und nicht delegieren können, wenn Sie einen WCF-Dienst aufrufen, der die Net.tcp-Bindung mit Transportsicherheit, Windows-Transportanmeldeinformationen und keine Schutzebene verwendet.

Ursprüngliche Produktversion:   Windows Communication Foundation
Ursprüngliche KB-Nummer:   2970779

Problembeschreibung

Stellen Sie sich folgendes Szenario vor:

  • Sie haben einen WCF-Dienst, der die Net.tcp-Bindung mit Transportsicherheit, Windows-Transportanmeldeinformationen verwendet und die Schutzebene auf keine festgelegt hat, wie im folgenden Beispiel:

     <netTcpBinding>
       <binding name="NetTcpBindingConfig">
          <security mode="Transport">
             <transport clientCredentialType="Windows" protectionLevel="None" />
          </security>
       </binding>
    </netTcpBinding>
    
  • Sie konfigurieren Ihren Endpunkt und geben eine gültige Identität mithilfe der Bindung wie folgt an:

     <endpoint
       address="net.tcp://srv1/Service/Service1.svc"
       binding="netTcpBinding"
       bindingConfiguration="NetTcpBindingConfig"
       contract="Contoso.IService1" behaviorConfiguration="NoNTLM"
       name="NetTcpContosoService">
       <identity>
          <servicePrincipalName value="WCFService/ContosoService" />
       </identity>
    </endpoint>
    (...)
    <behaviors>
       <endpointBehaviors>
          <behavior name="NoNTLM">
             <clientCredentials>
                <windows allowNtlm="false"/>
             </clientCredentials>
          </behavior>
       </endpointBehaviors>
    </behaviors>
    
  • Sie erstellen einen Proxy und rufen diesen WCF-Dienst auf.

In diesem Szenario werden Sie über NTLM anstelle von Kerberos authentifiziert und können nicht delegieren. Der Teil, der den Dienst aufruft, sieht wie folgt aus:

Service1Client client = null;
try
{
    client = new Service1Client("NetTcpBindingConfig");
    string returnStr = client.GetData(5);
    Console.WriteLine(returnStr);
    client.Close();
}
catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
    if(client != null)
    {
        client.Abort();
    }
}

Wenn System.Net Ablaufverfolgungen aktiviert sind, wird angezeigt, dass NTLM vor dem Versuch, Kerberos zu verwenden, verwendet wurde:

System.Net.Sockets Verbose: 0 : [5964] DNS::GetHostEntry(srv1)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Ausführlich: 0 : [5964] DNS::GetHostByName(srv1)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Ausführlich: 0 : [5964] Beenden von DNS::GetHostByName() -> IPHostEntry#14993092
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Ausführlich: 0 : [5964] Beenden von DNS::GetHostEntry() -> IPHostEntry#14993092
DateTime=2014-05-09T12:57:41.3298728Z System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Socket(AddressFamily#2)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Ausführlich: 0 : [5964] Beenden von Socket#720107::Socket()
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Verbinden(10.1.0.5:808#403439906)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Information: 0 : [5964] Socket#720107 – Erstellte Verbindung von 10.1.0.10:46321 bis 10.1.0.5:808.
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] Beenden von Socket#720107::Verbinden()
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] Socket#720107::Send()
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] Daten aus Socket#720107::Send DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] 00000000 : 00 01 00 01 02 02 31 6E-65 74 2E 74 63 70 3A 2F : .≡ 1net.tcp:/
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] 00000010 : 2F 73 72 76 31 2F 53 65-72 76 69 63 65 2F 53 65 : /srv1/Service/Se
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] 00000020 : 72 76 69 63 65 31 2E 73-76 63 03 08 00 00 00 00 : rvice1.svc."
DateTime=2014-05-09T12:57:41.3454728Z System.Net.Sockets Ausführlich: 0 : [5964] Beenden von Socket#720107::Send() -> Int32#58
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Ausführlich: 0 : [5964] Socket#720107::Send()
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Ausführlich: 0 : [5964] Daten aus Socket#720107::Send
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Ausführlich: 0 : [5964] 00000000 : 09 15 61 70 70 6C 69 63-61 74 69 6F 6E 2F 6E 65 : .. application/ne
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Ausführlich: 0 : [5964] 00000010 : 67 6F 74 69 61 74 65 : gotiate
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Ausführlich: 0 : [5964] Beenden von Socket#720107::Send() -> Int32#23
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Ausführlich: 0 : [5964] Socket#720107::Receive()
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Ausführlich: 0 : [5964] Daten aus Socket#720107::Receive
DateTime=2014-05-09T12:57:42.1098728Z
System.Net.Sockets Ausführlich: 0 : [5964] 00000000 : 0A : .
DateTime=2014-05-09T12:57:42.1098728Z
System.Net.Sockets Ausführlich: 0 : [5964] Beenden von Socket#720107::Receive() -> Int32#1
DateTime=2014-05-09T12:57:42.1098728Z
System.Net Informationen: 0 : [5964] Aufzählen von Sicherheitspaketen:
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] Aushandeln
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] NegoEx enumeration
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] Kerberos
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] NTLM
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] Schannel
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] Microsoft Unified Security Protocol Provider
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] WDigest
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] TSSSP
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] pku2u
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] CREDSSP
DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] AcquireDefaultCredential(package = NTLM, intent = Outbound) DateTime=2014-05-09T12:57:42.1254728Z
System.Net Informationen: 0 : [5964] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY,
context = (null), targetName = WCFService/ContosoService, inFlags = Connection, AcceptIntegrity) DateTime=2014-05-09T12:57:42.1254728Z

Wichtig

Obwohl die Identität im Endpunkt zusammen mit der Konfiguration des Dienstprinzipalnamens (SERVICE Principal Name, SPN) erforderlich ist, um die Kerberos-Delegierung in net.tcp zu aktivieren, wird dies in diesem Artikel nicht aufgelöst. Es wird davon ausgegangen, dass die Kerberos-Konfiguration ordnungsgemäß abgeschlossen wurde.

Ursache

Wenn die Schutzebene in der Bindung auf "None" festgelegt ist, wird NTLM auch dann verwendet, wenn NTLM aufgrund des Verhaltens nicht zulässig ist.

Lösung

Um dieses Problem zu beheben, verwenden Sie signieren auf Schutzebene, oder EncryptAndSign aktivieren Sie die Kerberos-Authentifizierung. Das folgende Beispiel ist die aktualisierte Bindungskonfiguration:

<netTcpBinding>
   <binding name="NetTcpBindingConfig">
      <security mode="Transport">
         <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
      </security>
   </binding>
</netTcpBinding>

Weitere Informationen