6 Stimmen

Ungültiges oder abgelaufenes Sicherheitskontext-Token im WCF-Webdienst

Alle,

Ich habe einen WCF-Webdienst (nennen wir ihn Dienst "B") unter IIS mit einem Dienstkonto (VM, Windows 2003 SP2) gehostet. Der Dienst bietet einen Endpunkt, der WSHttpBinding mit den Standardwerten mit Ausnahme von maxReceivedMessageSize, maxBufferPoolSize, maxBufferSize und einige der Timeouts, die erhöht wurden, verwendet.

Der Webdienst wurde mit dem Visual Studio Load Test Framework mit rund 800 gleichzeitigen Benutzern getestet und hat alle Tests erfolgreich bestanden, ohne dass Ausnahmen ausgelöst wurden. Der Proxy im Einheitstest wurde aus der Konfiguration erstellt.

Es gibt eine Sharepoint-Anwendung, die den Office Sharepoint Server Search-Dienst verwendet, um die Webdienste "A" und "B" aufzurufen. Die Anwendung erhält Daten vom Dienst "A", um eine Anfrage zu erstellen, die an den Dienst "B" gesendet wird. Die vom Dienst "B" kommende Antwort wird für die Suche indiziert. Der Proxy wird programmatisch mit Hilfe der ChannelFactory erstellt.

Wenn Dienst "A" weniger als 10 Minuten dauert, sind die Anrufe bei Dienst "B" erfolgreich. Wenn der Dienst "A" jedoch mehr Zeit in Anspruch nimmt (~20 Minuten), wird bei den Aufrufen von Dienst "B" die folgende Ausnahme ausgelöst:

Ausnahmemeldung: Ein ungesicherter oder nicht korrekt gesicherter Fehler wurde von der Gegenstelle empfangen. Siehe die innere FaultException für den Fehlercode und Details Innere Exception-Meldung: Die Nachricht konnte nicht verarbeitet werden. Dies liegt höchstwahrscheinlich daran, dass die Aktion "namespace/OperationName" falsch ist oder dass die Nachricht ein ungültiges oder abgelaufenes Sicherheitskontext-Token enthält oder dass eine Nichtübereinstimmung zwischen Bindungen besteht. Das Sicherheitskontext-Token wäre ungültig, wenn der Dienst den Kanal aufgrund von Inaktivität abbricht. Um zu verhindern, dass der Dienst inaktive Sitzungen vorzeitig abbricht, erhöhen Sie die Empfangszeitüberschreitung für die Bindung des Dienstendpunkts.

Die Einstellungen für die Bindung sind gleich, die Zeit auf dem Client-Server und dem Webdienst-Server wird mit dem Windows-Zeitdienst synchronisiert, dieselbe Zeitzone.

Wenn ich mir den Server ansehe, auf dem der Webdienst "B" gehostet wird, sehe ich, dass die folgenden Sicherheitsfehler protokolliert werden:

Quelle: Sicherheit

Kategorie: An-/Abmeldung

Ereignis ID: 537

Benutzer NT AUTHORITY \SYSTEM

Anmeldung fehlgeschlagen:

Der Grund: Bei der Anmeldung ist ein Fehler aufgetreten

Anmeldeart: 3

Logon-Prozess: Kerberos

Authentifizierungspaket: Kerberos

Status-Code: 0xC000006D

Substatus-Code: 0xC0000133

Nach der Lektüre einiger Blogs im Internet bedeutet der Statuscode STATUS_LOGON_FAILURE und der Substatuscode STATUS_TIME_DIFFERENCE_AT_DC. Aber ich habe bereits die Uhren von Server und Client überprüft und sie sind synchronisiert.

Ich habe auch bemerkt, dass das Sicherheitstoken irgendwo im Client-Server zwischengespeichert zu sein scheint, weil sie einen anderen Prozess haben, der den Webdienst "B" unter Verwendung desselben Dienstkontos aufruft und beim ersten Aufruf erfolgreich Daten erhält. Dann wird der Prozess gestartet, um die Indizes des Office Sharepoint Server-Suchdienstes zu aktualisieren, und er schlägt fehl. Wenn dann der erste Prozess erneut aufgerufen wird, schlägt er ebenfalls fehl.

Hat jemand Erfahrung mit dieser Art von Problemen oder hat irgendwelche Ideen?

Herzliche Grüße,

--Damian

5voto

Alex Punkte 1937

10 Minuten ist die Standard-Empfangszeitüberschreitung. Wenn ein Proxy länger als 10 Minuten im Leerlauf ist, wird die Sicherheitssitzung dieses Proxys vom Server abgebrochen. Aktivieren Sie die Protokollierung und Sie werden dies im Diagnoseprotokoll des Servers sehen. Die Fehlermeldung, die Sie gemeldet haben, passt zu diesem Verhalten. Suchen Sie in Ihrer Systemdiagnosedatei nach "SessionIdleManager". Wenn Sie ihn finden, ist das oben beschriebene Problem Ihr Problem.

Probieren Sie es aus und setzen Sie establishSecurityContext="false" für den Client und den Server.

3voto

MarkB Punkte 31

Rufen Sie den Dienstvorgang nicht in einer using-Anweisung auf. Verwenden Sie stattdessen ein Muster wie...

client = new ServiceClient("Ws<binding>")
try
{
    client.Operation(x,y);
    client.Close();
}
catch ()
{
    client.Abort();
}

Ich verstehe nicht, warum das funktioniert, aber ich würde vermuten, dass Close nicht aufgerufen wird, wenn der Proxy in der using-Anweisung den Bereich verlässt. Der Dienst wartet dann, bis receiveTimeout (in der Bindung) abgelaufen ist und bricht dann die Verbindung ab, wodurch nachfolgende Aufrufe fehlschlagen.

1voto

Assaf Stone Punkte 6269

Ich glaube, dass Ihr Kanal eine Zeitüberschreitung aufweist (wie Sie vermuten).

Wenn ich es richtig verstehe, sind es nicht die Aufrufe zum Dienst A die sich im Zeitablauf befinden, sondern für den Service B , vor nennen Sie Ihr Vorhaben.

Ich gehe davon aus, dass Sie Ihren Kanal erstellen vor Sie rufen den Service an A statt gerade noch rechtzeitig (d.h. vor dem Aufruf des Dienstes B ). Sie sollten den Kanal (Proxy, Service-Client) erstellen, bevor Sie ihn verwenden:

AResponse aResp = null;
BResponse bResp = null;
using (ServiceAProxy proxyA = new ServiceAProxy())
{
   aResp = proxyA.DoServiceAWork();
   using (ServiceBProxy proxyB = new ServiceBProxy())
   {
      bResp = proxyB.DoOtherork(aResp);
   }
}
return bResp;

Ich glaube jedoch, dass man, wenn man einmal darüber hinweg ist dass Problem (Dienst B fällt aus), werden Sie feststellen, dass der Proxy der Sharepoint-App (der den Dienst A ) eine Zeitüberschreitung. Um dieses Problem zu lösen, sollten Sie Ihr Dienstmodell von einem Anfrage-Antwort- zu einem Veröffentlichungs-Abonnement-Modell ändern.

Bei lang laufenden Diensten möchten Sie, dass Ihre Sharepoint-Anwendung den Dienst A abonniert und Dienst A seine Ergebnisse veröffentlicht, wenn er dazu bereit ist - unabhängig davon, wie lange es dauert.

Programming WCF Services (O'Reilly) von Juval Lowey bietet eine hervorragende Erklärung, und IDesign (Juvals Unternehmen) veröffentlichte ein großartiger Satz von Codierungsstandards für WCF sowie den Code für ein großartiges Publish-Subscribe-Framework .

Ich hoffe, das hilft, Assaf.

0voto

strongopinions Punkte 3877

Ich habe diesen Fehler gerade eben durch eine Dummheit ausgelöst. Ich habe einen Unit-Test, der das Systemdatum ändert, um einige zeitbasierte Funktionen zu testen. Und ich schätze, dass der offensichtliche Zeitunterschied zwischen dem Zeitpunkt, zu dem ich den Kontext erstellt habe, und dem Zeitpunkt, zu dem ich meine Methode aufgerufen habe (aufgrund der Änderungen am Systemdatum), dazu geführt hat, dass etwas abgelaufen ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X