Ich muss einen gestreamten WCF net.tcp-Dienstendpunkt mit WIF sichern . Es sollte eingehende Anrufe gegen unseren Tokenserver authentifizieren. Der Dienst wird gestreamt, da er für die Übertragung großer Datenmengen ausgelegt ist.
Dies scheint unmöglich zu sein. Und wenn ich den Haken nicht umgehen kann, wird mein Weihnachtsfest ruiniert und ich werde mich in einer Gosse zu Tode trinken, während fröhliche Käufer über meinen langsam abkühlenden Körper treten. Totes ernst, Leute.
Warum ist das unmöglich? Hier ist der Catch-22.
Auf dem Client muss ich einen Kanal mit dem GenericXmlSecurityToken erstellen, das ich von unserem Tokenserver erhalte. Kein Problem.
// people around here hate the Framework Design Guidelines.
var token = Authentication.Current._Token;
var service = base.ChannelFactory.CreateChannelWithIssuedToken(token);
return service.Derp();
Habe ich "no problemo" gesagt? Problemo. In der Tat NullReferenceException
Stil problemo.
"Bro", fragte ich das Framework, "prüfst du überhaupt nicht?" Das Framework war still, also habe ich es zerlegt und festgestellt
((IChannel)(object)tChannel).
GetProperty<ChannelParameterCollection>().
Add(federatedClientCredentialsParameter);
war die Quelle der Ausnahme und dass der GetProperty
Anruf zurückkehrte null
. Also, WTF? Es stellt sich heraus, dass, wenn ich die Nachrichtensicherheit aktiviere und den Clientanmeldeinformationstyp auf setze, IssuedToken
diese Eigenschaft jetzt im ClientFactory
(protip: Es gibt kein "SetProperty" -Äquivalent in IChannel, dem Bastard) vorhanden ist.
<binding name="OMGWTFLOL22" transferMode="Streamed" >
<security mode="Message">
<message clientCredentialType="IssuedToken"/>
</security>
</binding>
Süss. Keine NREs mehr. Jetzt ist mein Klient jedoch bei der Geburt fehlerhaft (liebe ihn immer noch, tho). Wenn ich die WCF-Diagnose durchforste (Protip: Lassen Sie Ihre schlimmsten Feinde dies tun, nachdem Sie sie niedergeschlagen und vor Ihnen gefahren haben, aber kurz bevor Sie die Wehklagen ihrer Frauen und Kinder genießen), sehe ich, dass dies auf eine Sicherheitslücke zwischen Server und Client zurückzuführen ist.
Das angeforderte Upgrade wird von 'net.tcp: // localhost: 49627 / MyService' nicht unterstützt. Dies kann auf nicht übereinstimmende Bindungen zurückzuführen sein (z. B. auf dem Client und nicht auf dem Server aktivierte Sicherheit).
Wenn ich die Diags des Hosts überprüfe (noch einmal: zerquetschen, fahren, Protokolle lesen, Wehklagen genießen), sehe ich, dass dies wahr ist
Die Protokolltypanwendung / ssl-tls wurde an einen Dienst gesendet, der diese Art der Aktualisierung nicht unterstützt.
"Nun, ich selbst", sagt ich, "ich schalte einfach die Nachrichtensicherheit auf dem Host ein!" Und ich mache. Wenn Sie wissen möchten, wie es aussieht, handelt es sich um eine exakte Kopie der Client-Konfiguration. Sieh nach oben.
Ergebnis: Kaboom.
Die Bindung ('NetTcpBinding', ' http://tempuri.org/ ') unterstützt Streaming, das nicht zusammen mit der Sicherheit auf Nachrichtenebene konfiguriert werden kann. Wählen Sie einen anderen Übertragungsmodus oder die Sicherheit auf Transportebene.
So kann mein Gastgeber nicht beide gestreamten und gesichert über Token sein . Fang-22.
tl; dr: Wie kann ich einen gestreamten net.tcp WCF-Endpunkt mit WIF sichern?
<security mode="Transport" /> <transport clientCredentialType="IssuedToken" /> </security>
TransportWithMessageCredential
Modus kann eine andere Option sein.Antworten:
WCF hat in einigen Bereichen Probleme mit Streaming (ich sehe Sie an, MTOM 1 ), da es ein grundlegendes Problem gibt, wie die Vorauthentifizierung nicht so durchgeführt wird, wie die meisten Leute denken, dass dies funktionieren sollte (dies betrifft nur nachfolgende Anforderungen für diesen Kanal , nicht die erste Anfrage) Ok, das ist also nicht genau Ihr Problem, aber bitte folgen Sie mir, da ich am Ende zu Ihnen komme. Normalerweise funktioniert die HTTP-Challenge folgendermaßen:
Wenn Sie jemals versuchen, das MTOM-Streaming auf einem WCF-Endpunkt auf dem Server zu aktivieren, wird dies nicht beanstandet. Wenn Sie es jedoch auf dem Client-Proxy konfigurieren (wie Sie sollten, müssen sie mit den Bindungen übereinstimmen), explodiert es in einem feurigen Tod. Der Grund dafür ist, dass die obige Abfolge von Ereignissen, die WCF zu verhindern versucht, folgende ist:
Beachten Sie, dass Sie gerade 200 MB an den Server gesendet haben, als Sie nur 100 MB senden mussten. Nun, das ist das Problem. Die Antwort besteht darin, die Authentifizierung beim ersten Versuch zu senden. Dies ist jedoch in WCF nicht möglich, ohne ein benutzerdefiniertes Verhalten zu schreiben. Wie auch immer, ich schweife ab.
Ihr Problem
Lassen Sie mich zunächst sagen, dass das, was Sie versuchen, unmöglich ist 2 . Damit Sie nicht mehr durchdrehen, lassen Sie mich Ihnen sagen, warum:
Es fällt mir auf, dass Sie jetzt in einer ähnlichen Klasse von Problemen wandern. Wenn Sie die Sicherheit auf Nachrichtenebene aktivieren, muss der Client den gesamten Datenstrom in den Speicher laden, bevor er die Nachricht mit der für ws-security erforderlichen Hash-Funktion und XML-Signatur schließen kann. Wenn es den gesamten Stream lesen muss, um die einzelne Nachricht zu signieren (was nicht wirklich eine Nachricht ist, sondern ein einzelner kontinuierlicher Stream), können Sie das Problem hier sehen. WCF muss es einmal "lokal" streamen, um die Nachrichtensicherheit zu berechnen, und es dann erneut streamen, um es an den Server zu senden. Dies ist eindeutig eine dumme Sache, daher erlaubt WCF keine Sicherheit auf Nachrichtenebene für das Streaming von Daten.
Die einfache Antwort hier lautet also, dass Sie das Token entweder als Parameter an den ursprünglichen Webdienst oder als SOAP-Header senden und ein benutzerdefiniertes Verhalten verwenden sollten, um es zu validieren. Sie können WS-Security nicht verwenden, um dies zu tun. Ehrlich gesagt ist dies nicht nur ein WCF-Problem - ich kann nicht sehen, wie es praktisch für andere Stapel funktionieren könnte.
Lösen des MTOM-Problems
Dies ist nur ein Beispiel dafür, wie ich mein MTOM-Streaming-Problem für die Basisauthentifizierung gelöst habe. Vielleicht können Sie sich also den Mut machen und etwas Ähnliches für Ihr Problem implementieren. Der springende Punkt dabei ist, dass Sie zum Aktivieren Ihres benutzerdefinierten Nachrichteninspektors alle Sicherheitsbegriffe auf dem Client-Proxy (auf dem Server aktiviert) deaktivieren müssen, mit Ausnahme der Transportebene (SSL):
Beachten Sie, dass ich die Transportsicherheit hier deaktiviert habe, da ich dies selbst mithilfe eines Nachrichteninspektors und benutzerdefinierten Verhaltens bereitstellen werde:
Dieses Beispiel ist also für alle gedacht, die unter dem MTOM-Problem leiden, aber auch als Grundgerüst für Sie, um etwas Ähnliches zu implementieren, um Ihr vom primären WIF-gesicherten Token-Dienst generiertes Token zu authentifizieren.
Hoffe das hilft.
(1) Große Datenmenge und Streaming
(2) Nachrichtensicherheit in WCF (siehe "Nachteile")
quelle
MTOM and Basic Authorization
und MTOM und OAuth2 ?