Laden...

WCF Flut: Hilfe!

Erstellt von syn87 vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.856 Views
S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren
WCF Flut: Hilfe!

Hallo zusamm,

seit einigen Tagen beschäftige ich mich jetzt mit WCF und muss sagen, vom Funktionsumfang ist das ganze ja noch n Tick schlimmer als .NET Remoting. Was ich damit sagen will ist, dass ich mittlerweile garnicht mehr weiß, was ich alles gelesen hab, und was davon wichtig für mich ist.

Aus diesem Grund wollte ich euch gesammelt mal Fragen, welche Dokumentationen ihr für meinen konkreten Fall empfehlen könnt:

  • Context Unterstützung
  • Authorisierung über Windows Account

Beiläufig stell ich mir momentan immer noch die Frage (da ich noch nicht soweit bin), wie ich meine Anwendung denn testen kann. Es sollte ja selbst für Debug auf 2 Betriebssystemen laufen, oder wuerde vllt auch eins reichen? Wobei ich mir dann die Frage stelle, wie ich rausbekomme, dass er die Identität vom Aufrufer nimmt, oder die eigene. Ist ja dann die selbe?!

LG

3.728 Beiträge seit 2005
vor 14 Jahren
WCF Featureitis

Hallo syn87,

WCF vereinigt alles, was man vorher mit Remoting, MSMQ, Webservices und zusätzlichen Libraries (für Dinge wie z.B. REST) gemacht hat, in einem einzigen großen Programmiermodell. Deshalb ist WCF so ein großes unhandliches Monster.

Der Großteil der Funktionen ist aber an bestimmte Bindungen (Bindings) geknüpft. Du musst Dir deshalb zuerst überlegen, welche Art von Kommunikation für Deine Anwendung benötigt wird. Wenn Du z.B. schnell im LAN kommunizieren willst, verwendest Du das NetTcpBinding. Wenn Du möglichst Interoperable Webservices schreiben willst, dann das BasicHttpBinding. Für Webservices nach dem Neusten Stand der Technik, z.B. eher das WsHttpBinding. Möchtest Du mittels MSMQ-Nachrichten kommunizieren, passt das NetMsmqBinding. Usw ...

Je nach Binding können bestimmte WCF-Features nicht genutzt werden. Nicht jedes Binding unterstützt z.B. Duplex-Kommunikation oder Verlässliche-Datenübertragung. Auch die unterstützten Authentifizierungs- und Aauthorisierungsverfahren hängen vom Binding ab.

Überlege Dir also zuerst, was Du genau brauchst und wähle dann dafür das passende Binding. Für 95% der Fälle solltest Du ein passendes Standardbinding finden. Alle Infos über die vorgefertigten Standardbindings findest Du in der MSDN Library (genauer und ausführlicher ist kein Fachbuch).

Was das Testen angeht, würde ich einen separaten Testserver einrichten, damit wirklich mit echter Netzerkkommunikation getestet wird.

Windows-Authorisierung erfolgt ganz ähnlich wie bei Remoting über WindowsPrincipal. Bei NetTcpBinding ist Windows-Auth. die Standardeinstellung für die Identitätsprüfung.

6.911 Beiträge seit 2009
vor 14 Jahren

Hallo,

zur Auswahl der Standardbindungen gibt es nettes Entscheidungsdiagramm: Choosing the right WCF binding.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren
Context-Funktionen & ApplicationServer

Hallo ihr beiden,

danke für die beiden Antworten, vor allem Rainbird für den doch ziemlich langen Post 😃 An sich sollte meine Frage aber auf etwas anderes zielen. Ich habe mich bereits für das NetTcpBinding entschieden, da es in der Tat eine Anwendung sein soll, die mittels Client und Server über das Netzwerk kommuniziert. An den Principal komm ich mittlerweile auch ran. Was ich mich aber immernoch frage ist, wie kann ich ContextDaten setzen. Also ähnlich wie beim .NET Remoting mit CallContext.SetLogicalData usw.. Ich geh davon aus dass ich weiterhin das NetTcpContextBinding nutzen muss. Richtig?

@Rainbird:

Dein Applikationsserver ist nach wie vor ein schönes Beispiel um einen Einstieg in den ganzen Remoting Kram zu bekommen. Hat mir wirklich sehr geholfen! Danke an dieser Stelle dafür. Allerdings stell ich mir mittlerweile auch ein paar Fragen, warum du was wie gemacht hast. Einige davon wären:

  • Warum sind Funktionen wie Login, Logoff, RenewSession usw. in der API (BasisContract)? Sollte die konkrete Implementierung nicht beim Server liegen? (Ist letztendlich wahrscheinlich egal, aber ich habs mich trotzdem gefragt 😃

-Wenn es um den SecurityService geht. Könnte man nicht alle Funktionen innerhalb des Servers auf eine static class umleiten? Ich stell mir das quasi so vor, dass es einen SecurityService gibt der nur die Funktionen Login, Renew und Logoff hat. Diese leiten innerhalb des servers dann auf Server.Login/Renew/Logoff um. Dieser "Singleton" kann dann die Sessions verwalten und gibt den anderen Diensten die möglichkeit, per IsInRole(...) einzelne Rechte abzufragen. Wäre das so prinzipiell auch möglich, oder hab ich bei deinem AppServer nur was falsch verstanden?

Liebe Grüße

--------------------------------------- EDIT ----------------------------------------------
Hier ein kleiner Zwischenstand (da ich trotz des Forums versuche, meine Probleme selber zu loesen):

Soweit ich gelesen hab, muesste ich IClientMessageInspector und IDispatchMessageInspector verwenden. Mir erscheint das jedoch etwas viel Aufwand. Alles was ich benötige ist eigntl, dass der Server ein paar Daten einspeisen kann, und zum späteren Zeitpunkt darauf zugreifen kann. Nach Möglichkeit über alle zwischen Client udn Server bestehende Dienste.

Ein kleines Szenario wäre also:

  • Client: Login (SecurityService)
  • Server: erstellt GUID für Client und hängt diese in den Context
  • Client: GetCustomers (CustomerService)
  • Server: kann auf Context zugreifen, erkennt GUID usw.

LG und danke an jeden der so viel liest 😃

3.728 Beiträge seit 2005
vor 14 Jahren
  • Warum sind Funktionen wie Login, Logoff, RenewSession usw. in der API (BasisContract)? Sollte die konkrete Implementierung nicht beim Server liegen? (Ist letztendlich wahrscheinlich egal, aber ich habs mich trotzdem gefragt 😃

In der API ist nur die Schnittstelle ISecurityService. Die konkrete Implementierung liegt im Namensraum Rainbird.AppServer und nicht im Namensraum Rainbird.AppServer.API. Deshalb würde ich schon sagen, dass die Implementierung beim Server liegt.

-Wenn es um den SecurityService geht. Könnte man nicht alle Funktionen innerhalb des Servers auf eine static class umleiten? Ich stell mir das quasi so vor, dass es einen SecurityService gibt der nur die Funktionen Login, Renew und Logoff hat. Diese leiten innerhalb des servers dann auf Server.Login/Renew/Logoff um. Dieser "Singleton" kann dann die Sessions verwalten und gibt den anderen Diensten die möglichkeit, per IsInRole(...) einzelne Rechte abzufragen. Wäre das so prinzipiell auch möglich, oder hab ich bei deinem AppServer nur was falsch verstanden?

Natürlich könnte man das auch anders machen und Dinge wie Sicherheit und Sitzungsverwaltung in verschiedenen Klassen unterbringen, aber das sind Feinheiten. Ich habe den Sicherheitsdienst auch als Singleton laufen, allerdings habe ich den Singleton auf einer anderen Ebene implementiert.
Mein Ziel war es, die eigentliche Host-Klasse möglichst schlank zu halten.

Soweit ich gelesen hab, muesste ich IClientMessageInspector und IDispatchMessageInspector verwenden. Mir erscheint das jedoch etwas viel Aufwand. Alles was ich benötige ist eigntl, dass der Server ein paar Daten einspeisen kann, und zum späteren Zeitpunkt darauf zugreifen kann. Nach Möglichkeit über alle zwischen Client udn Server bestehende Dienste.

Es gibt keinen direkten Ersatz für CallContext in WCF. Du müsstest Dir das selber bauen, was - wie Du bereits festgestellt hast - sehr aufwändig ist. Ich würde bei WCF eher den Ansatz wählen, alles mit Nachrichten zu modellieren (also nicht mehrere Parameter bei den Dienstfunktionen, sondern nur einen für die eingehende Nachricht). Das Sitzungsticket kannst Du dann in die Nachricht packen. Du musst es halt in jede Nachricht packen. Gefällt mir auch nicht besonders, aber WCF kann´s einfach nicht.

3.003 Beiträge seit 2006
vor 14 Jahren

Soweit ich gelesen hab, muesste ich IClientMessageInspector und IDispatchMessageInspector verwenden. Mir erscheint das jedoch etwas viel Aufwand. Alles was ich benötige ist eigntl, dass der Server ein paar Daten einspeisen kann, und zum späteren Zeitpunkt darauf zugreifen kann.

Hm, aber wieso dann was an den Messages ändern? Die Inspectors geben dir halt die Möglichkeit, an den Nachrichten vor und nach dem Übergang Client/Server noch was zu ändern.
Nun hab' ich den Nachteil, dass ich remoting nicht gut genug kenne, um zu wissen, was CallContext genau macht, und was du also da abbilden willst. Ich kann also nur raten - schau dir mal OperationContext (OperationContextScope) an. Du hast auch die Möglichkeit, (z.B.) im CheckAccessCore eines AuthorizationManagers am Context der aktuellen Operation was zu ändern (um später drauf zuzugreifen). Die Frage ist für mich halt, was du damit bezwecken möchtest.

Die vier von dir angeführten Punkte erinnern mich eher an ein Authentifizierungsszenario. Dann wäre evtl ServiceSecurityContext dein Stichwort.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Den ServiceSecurityContext benutze ich bereits - Erfolgreich. Grund für mich einen CallContext zu verwenden ist der, dass ich wie bereits erwähnt eine Session erstellen kann. Ich orientiere mich dabei sehr am Beispiel von Rainbird - ist für mich auch irgendwie schlüssig.
Dazu gehört unter anderem der LockingService. Dieser muss ja zwangsweise auf einer SessionId basieren, die vom Server kommt. Der ServiceSecurityContext wuerde dafuer nicht genuegen, da z.b. im Falle eines Programmabsturzes ein Element ewig gelockt bleiben würde. Genauer Mechanismus wäre dabei wie folgt:

  • LockingAnforderung<Customer>(CustomerId)
  • Per Timer stetig die Session Renew'en
  • Server verlängert Locking

Bei einem gecrashten App wäre dann die Ressource nicht mehr offen aber dennoch geblockt. Ähnliches könnte man z.b. über die Login Methode beseitigen (indem man alle Lockings löscht), aber ich weiss nicht so recht, ob das ein guter Weg ist. Was meint ihr? (Ist mir naemlich grad erst eingefallen 😃

LG

3.728 Beiträge seit 2005
vor 14 Jahren

Nun hab' ich den Nachteil, dass ich remoting nicht gut genug kenne, um zu wissen, was CallContext genau macht, und was du also da abbilden willst. Ich kann also nur raten - schau dir mal OperationContext (OperationContextScope) an. Du hast auch die Möglichkeit, (z.B.) im CheckAccessCore eines AuthorizationManagers am Context der aktuellen Operation was zu ändern (um später drauf zuzugreifen). Die Frage ist für mich halt, was du damit bezwecken möchtest.

Bei Remoting gibt es einen zentralen Aufrufkontext. In den kann man einmalig Daten reinstecken, welche dann automatisch an ALLE entfernten Methodenaufrufe drangehängt werden. Ich kann so z.B. einen Sitzungsschlüssel clientseitig in dieses CallContext legen und diesen serverseitig wieder auslesen. So kann der Dienst serverseitig mit geringem Aufwand prüfen, ob sich der Aufrufer zuvor korrekt am Server angemeldet hat, ob seine Sitzung noch gültig ist und ob er überhaupt Mitglied der nötige Rolle ist, um die aktuelle Dienstoperation aufzurufen. Natürlich kann man das auch anders lösen, aber der Knackpunkt sind - zumindest bei Remoting - Dienste, die wieder andere Dienste aufrufen. Client X ruft Dienst A auf dieser ruft Dienst B auf. Bei Dienst A ist der Identifizierte Aufrufer der Benutzer des Clients, aber bei Dienst B ist der Identifizierte Aufrufer dann natürlich der Benutzer des Appserver-Dienstkontos unter dem Dienst A ausgeführt wird. Wenn ich aber einen Sitzungsschlüssel beim Client X in den Remoting CallContext lege, wird dieser über alle Dienst-Hops durchgeschleift. Ich kann den urspünglichen Aufrufer und dessen Sitzung also immer abfragen, egal wie lange die Aufrufkette ist.

Bei WCF muss ich mich out-of-the-box selber darum kümmern, dass der Sitzungsschlüssel weitergegeben wird. Da hier standardmäßig nur ein OperationContext verfügbar ist, müsste ich das Ganze also in jeder einzelnen Dienstoperation abhandeln. Oder ich schreibe entsprechende Behaviors, die das entsprechend in den Message-Header o.ä. packen und da auch wieder rausholen. Das ist aber recht viel Aufwand.

Das Problem ist, dass WCF keine Entsprechung zu ASP.NET-Sessions hat.

3.003 Beiträge seit 2006
vor 14 Jahren

Oder ich schreibe entsprechende Behaviors, die das entsprechend in den Message-Header o.ä. packen und da auch wieder rausholen. Das ist aber recht viel Aufwand.

...wäre aus meiner Sicht ja auch die richtige Vorgehensweise, um Sessionverhalten nachzuempfinden (Header dazupacken, bzw auslesen und entsprechend authentifizieren - könnte man per Behaviour und / oder Auth-Manager lösen).

Das Problem ist, dass WCF keine Entsprechung zu ASP.NET-Sessions hat.

Ich nehme an, weil ein derartiger Sessionbegriff nicht WCF-weit Sinn ergibt und weil zum zweiten kein Interesse bestand, ASP.NET-Verhalten in WCF abzubilden. Für sessionweit gültige Serviceinstanzen gibts ja schließlich InstanceContextMode.PerSession und SessionMode. Also so richtig händisch nachprogrammieren muss man nicht.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

3.728 Beiträge seit 2005
vor 14 Jahren

... Für sessionweit gültige Serviceinstanzen gibts ja schließlich InstanceContextMode.PerSession und SessionMode. Also so richtig händisch nachprogrammieren muss man nicht.

Diese Sessions können doch aber nicht über mehrere Services hinweg genutzt werden, sondern dienen nur zur Korrelation von Nachrichten etc., oder?
Auch werden WCF-Sessions vom Client erzeugt und ASP.NET-Sessions vom Server.

Es ist einfach ein ganz anderes Konzept (Nicht schlechter, sondern einfach anders).

Leute aus der Remoting- bzw. Enterprise.Services-Ecke tun sich damit teilweise sehr schwer. Für Enterprise.Services gibt es ja ein WCF-Binding für Interop-Szenarien, aber die Remoting-Gemeinde steht im Regen. Entweder weiter mit Remoting arbeiten, oder alles neu schreiben. "Hello World"-Remoting-Anwendungen lassen sich mit ein paar Handgriffen migrieren (NetTcpBinding + ChannelFactory), aber bei größeren Anwendungen fehlen einfach bestimmte Features bzw. sind die Konzepte zu verschieden.

Da die interne Cross-AppDomain-Kommunikation im Framework mit Remoting funktioniert, wird uns das gute alte Remoting wohl noch lange erhalten bleiben. Support Policy-Panik ist also gar nicht angebracht. Außerdem ist Remoting auch erweiterbar (dort heißt es eben nicht Behavior, sondern ChannelSink). VBA ist auch seit Jahren totgesagt und kommt nach wie vor mit jeder neuen Office-Version wieder im Gepäck mit (VBA ist genauso wie Remoting für bestimmte Szenarien unübertroffen und kann ncht einfach durch VSTO etc. ersetzt werden). Zugegeben passt der Vergleich mit VBA nicht ganz, aber es geht in eine ähnliche Richtung.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Ist immer wieder interessant deine Beiträge zu lesen 😃 Wie lang programmierst du schon .NET und wie hast du dir das alles angeeignet?

Zum Session Kram hier noch eine Idee von mir. Ich beschreib das wieder in gewohnter Stichpunkt Form. Vllt hat ja jemand n Kommentar oder Kritik dazu.

  • Client generiert GUID
  • Login-Versuch, true = Success, false => 5 neue Versuche, danach Meldung "Andere Session aktiv. Übernehmen?" -> Sprich die Session für eine andere AppInstanz wird verworfen.
  • Stetiges RenewSession() mit der GUID um alle assoziierten Daten zu halten. Z.b. gelockte Items
  • Bei Timeout -> Free Locked Items
  • Beim Schließen Logout mit GUID -> Alle Daten auf dem Server zerstören

Auf diesem Weg würde das Mitsenden der SessionID bei allen Methoden erspart bleiben, da pro Benutzer eh nur eine AppInstanz erlaubt ist. Für eine MDI Applikation duerfte das ja kein Problem sein.

LG und danke schonmal für die vielen informativen Posts 😃

3.728 Beiträge seit 2005
vor 14 Jahren
Sitzungsgeplänkel

Hallo syn87,

ich programmiere seit der 1.Beta-Version des .NET Frameworks 1.0 auf der .NET-Plattform. Zuvor habe ich VBA, VB6 und ein kleines bischen C++ programmiert. Wie ich mir das angeeignet habe? Viel MSDN gelesen, ein größeres Projekt früh mit der neuen Technologie unter gewissem Erfolgsdruck hochgezogen und vor allem viele Fragen hier im Forum beantwortet. Bei jeder Frage hier, die ich beantworte, muss ich mich in ein konkretes Problem hineindenken und werde oft mit Anforderungen und Sichtweisen konfrontiert, die ich vorher noch nicht kannte. Dabei lernt mein einfach sehr viel und sehr schnell. Und man blickt auch mal über den Tellerrand.

Ich habe Deinen Letzten Session-Vorschlag noch nicht so ganz verstanden. Sorry. Kannst Du das noch etwas genauer beschreiben?

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Nunja. Es würde ebenso wie bei dir auf einem SecurityService basieren. Dieser stellt folgende Methoden bereit:


// gibt TRUE wenn Login erfolgreich, sonst FALSE (wenn Principal bereits Session hat)
bool Login(GUID guid);

// ist in der Lage eine bestehende Session zu überschreiben, TRUE wenn erfolgreich
bool ForceLogin(GUID guid);

// frischt TimeStamp auf (Timeout für Locking Items)
// TRUE alles is in Ordnung
// FALSE aktuelle Session wurde überschrieben
bool Renew(GUID guid);

// löscht Session Items
void Logoff(GUID guid);

Nun ein kleines Beispiel 😃 Es geht dabei um einen Rechner mit einem bestimmten Nutzer, welcher an einer Domain angemeldet ist.

  • Startet Instanz (A) -> Login

  • Stetiges Renew (Timer) und normales Arbeiten

  • Startet Instanz (B) -> Login
    -> returns FALSE

  • Vorhandene Session überschreiben? (MessageBox)

    • Ja -> ForceLogin
    • Nein -> App Close
  • Login erklaert sich von alleine 😃

LG

3.728 Beiträge seit 2005
vor 14 Jahren

Mmm...? Aber wie kommt der Sitzungsschlüssel von Dienst A nach Dienst B?

Das dauernde Refreshing gefällt mir nicht so ganz, da dadurch eine dauerhafte Grundlast auf Netzwerk und Server verursacht wird, die eigentlich nicht sein müsste.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Es wuerde in dem Sinne keinen Sitzungsschluessel geben, man müsste immer erst den Principal aufrufen.
Das mit der permanent Last stimmt natürlich. Wobei ich dem gegenüber jetzt behaupten würde, dass da nich wirklich viel "Last" über die Leitung geschoben wird.

LG

3.728 Beiträge seit 2005
vor 14 Jahren
Dienst zu Dienst

Dann funktioniert es aber nicht, wenn sich die Dienste auch untereinander konsumieren, wie z.B. in folgendem Blog-Eintrag dargestellt: http://yellow-rainbird.de/blogs/rainbird/archive/2008/11/11/dienste-einer-n-tier-anwendung-in-eine-klare-hierarchie-bringen.aspx

Bereits beim ersten Aufruf eines Dienstes, der nicht von einem Client, sondern von einem anderen Dienst kommt, wäre der Principal immer das Benutzerkonto des Host-Prozesses, in dem der aufrufende Dienst aufgehängt ist.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Im ernst? 😃 Na dann kann man ja immernoch intern den Principal weitergeben. Jedenfalls werd ich das denke mal genau so implementieren. Für ein mittelständisches Unternehmen reichts. Vllt wirds dann spaeter nochmal geaendert.

LG

3.728 Beiträge seit 2005
vor 14 Jahren
Sitzungsschlüssel

Dann gebe ich lieber den Sitzungsschlüssel weiter, statt den Principal. Vor allem spare ich mir so dauernde Sicherheitsprüfungen, solange die Sitzung nicht abgelaufen ist.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Nur wäre man dann wieder bei dem Punkt, an dem man in jedem Methodenaufruf seine Session packen muss. Also ist sicher beides nicht so ganz optimal. Da überleg ich doch glatt wieder, ob ich WCF nicht sein lasse und doch Remoting verwende :\

3.728 Beiträge seit 2005
vor 14 Jahren
Back to the roots

Ich für meinen Teil werde weiterhin Remoting einsetzen. Wenn ich doch mal einer Java-Anwendung kommunizieren muss, kann ich jederzeit mit WCF einen Wrapper bauen, der mir den Zugriff auf meine Remoting-Dienste über SOAP etc. ermöglicht.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Ich denke auch das wird das Vernuenftigste sein. Zumindest wenn man noch auf bestimmte Features von Remoting angewiesen ist, wie z.b. dem CallContext. Läuft ja nich weg 😃