WCF-Dienstvorgänge, die asynchron über freigegebene Clientproxys mit Identitätswechsel aufgerufen werden, können den falschen Identitätswechselkontext verwenden.
Dieser Artikel hilft Ihnen, das Problem zu beheben, dass Windows WCF-Dienstvorgänge (Communication Foundation), die asynchron über freigegebene Clientproxys mit Identitätswechsel aufgerufen werden, möglicherweise den falschen Identitätswechselkontext verwenden.
Ursprüngliche Produktversion: Windows Communication Foundation
Ursprüngliche KB-Nummer: 2856654
Problembeschreibung
Stellen Sie sich folgendes Szenario vor:
Ihr Client verwendet WCF-Proxys, um Dienstvorgänge aufzurufen.
Ihr Client nutzt die Clientproxys zum automatischen Öffnen.
Ihr Client verwendet den Identitätswechsel.
Der Client ruft die Vorgänge asynchron auf.
Sie verwenden dieselbe Clientproxyinstanz für mehrere Verwendungszwecke.
In diesem Szenario können Situationen auftreten, in denen der Dienstvorgang nicht unter dem beabsichtigten Identitätswechselkontext ausgeführt wird.
Aufgrund des Verlusts des Identitätswechselkontexts wird keine Ausnahme ausgelöst oder ein Fehler protokolliert. Ob der Vorgang erfolgreich ist oder fehlschlägt, hängt davon ab, was der Dienstvorgang zu tun versucht. Bei wahrscheinlichen Fehlern, die beobachtet werden, werden Autorisierungsfehler beim Versuch, Kundencode innerhalb des Dienstvorgangs auszuführen, auftreten.
Eine Möglichkeit, dieses Problem zu diagnostizieren, besteht darin, den Inhalt des Dienstvorgangs zu ServiceSecurityContext.Current.WindowsIdentity überprüfen. Wenn die Identität zeitweise anders ist als erwartet, tritt möglicherweise dieses Problem auf.
Ursache
Bevor ein Clientproxy einen Vorgang aufrufen kann, muss er geöffnet werden. Es kann explizit aus Ihrem eigenen Code geöffnet werden, oder Sie können wcf verwenden, um automatisch für Sie zu öffnen.
Das Problem tritt auf, weil das für asynchrone Vorgänge erforderliche automatische Öffnen selbst asynchron erfolgt. Und wenn der gleiche Proxy für mehrere asynchrone Vorgänge verwendet wird, müssen alle außer dem ersten warten, bis der anfängliche asynchrone Vorgang erfolgreich warte. Abhängig von den Threads, die diese Vorgänge aufrufen, und dem Timing ist es möglich, dass der Identitätswechselkontext, der beim ersten automatischen Öffnen vorhanden ist, verloren geht.
Lösung
Die Lösung für dieses Problem ist einfach: Verlassen Sie sich nicht auf das automatische Öffnen, sondern öffnen Sie stattdessen den Clientproxy explizit selbst.
Indem Sie den Clientproxy selbst öffnen, stellen Sie sicher, dass die zugrunde liegenden Verbindungen im richtigen Identitätswechselkontext vollständig geöffnet sind, bevor der erste Vorgang aufgerufen wird.
Nachfolgend sehen Sie ein Beispiel für die explizit client.Open() empfohlene Vorgehensweise.
public static void Main(string[] args)
{
NetTcpBinding binding = new NetTcpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
binding.Security.Transport.ProtectionLevel = ProtectionLevel.None;
string address = "net.tcp://localhost:8887/EchoService/svc";
Service1Client client = new Service1Client(binding, new EndpointAddress(address));
// Explicit open is required when using async client operations with impersonation
using (Impersonation p = new Impersonation("myDomain", "myUser", "myPassword"))
{
client.Open();
}
for (int i = 0; i < 10; ++i)
{
ThreadPool.QueueUserWorkItem((state) =>
{
using (Impersonation p = new Impersonation("myDomain", "myUser", "myPassword"))
{
client.BeginGetData(new GetDataRequest((int) state), (ar) =>
{
GetDataResponse response = client.EndGetData(ar);
Console.WriteLine("Response was: '{0}'", response.GetDataResult);
}, null);
}
}, i);
}
Console.WriteLine("Press ENTER...");
Console.ReadLine();
Environment.Exit(0);
}
Weitere Informationen
Das explizite Öffnen von Clientproxys, wenn sie freigegeben und asynchron verwendet werden, wird aus mehreren Gründen als bewährte Methode betrachtet. Weitere Informationen finden Sie unter Bewährte Methode: Immer WCF-Clientproxy explizit öffnen, wenn er freigegeben ist.