[DE] [bad English if required for answer;-] Starthilfe Sessions/Authentication (solved)

Topics: Technical Support
Aug 3, 2011 at 8:48 PM
Edited Aug 3, 2011 at 8:50 PM

Hallo zusammen.

Nach dem ich die letzten Tage ein wenig mit eurem Framework gespielt habe, bin ich bisher ziemlich begeistert davon. Vorneweg also erstmal vielen Dank, für die Arbeit, die ihr hier reinsteckt. Mittlerweile stecke ich allerdings bei einigen Sachen fest, die ich scheinbar schlicht nicht kapiere.

1. Mit dem TcpBinaryProtocol habe ich bisher immer eine Verbindung zustande bekommen. Da ich dort bisher nicht herausgefunden habe, ob und wie ich (selbstgebastelte) Authentifizierung und ConnectionKeepAlive hinbekomme, versuche ich derzeit mit dem TcpDuplexServerProtocolSetup mein Glück. Ziel ist es eine Klasse bereitzustellen, die Sessionverwaltung, Authentifizierung gegen eine Account-Collection und Registrierung/Löschen von Accounts bewerkstelligt und diese etwa wie folgt bereitzustellen. Vielleicht ist das ja aber auch schon grundlegend falsch vom Ansatz her.

public class CServerMain : IServer, ISessionManager, IAuthenticationProvider
    {
        public AccountCache Accounts;
        public Dictionary<Guid, ServerSession> Sessions;
        //Interface member .... and my own stuff
        ...
    }

Soweit bin ich bisher allerdings noch nicht einmal gekommen. Initialisiert wird derzeit wie folgt:

//Server
TcpDuplexServerProtocolSetup TcpProtocol = new TcpDuplexServerProtocolSetup(Port, new NullAuthenticationProvider(), //Use Servermain for Auth. later ... false, // no encryption "", // so no encryption method ?!? false, // nothing of this too ?!? true, // this is just for TCP-Connections? Not for sessions, right? 60000, // this too? 1000); // this too? Host = new ZyanComponentHost("ServerHost", TcpProtocol2, new InProcSessionManager()); //Use Servermain as Sessionhandler later ... Host.RegisterComponent<IServer, CServerMain>(ServerMain);
//Client TcpDuplexClientProtocolSetup protocolSetup = new TcpDuplexClientProtocolSetup( false, // no encryption "", // so no encryption method ?!? 3, // maxAttempts ... to connect? Authenticate? false, // nope true, // this is just for TCP-Connections? Not for sessions, right? 60000, // this too? 1000); // this too? ZyanConnection connection = new ZyanConnection( "tcp://localhost:26999/ServerHost", protocolSetup, null, //Does null-authentication provider take Null-Credentials? Hope so. false, true); IServer server = connection.CreateProxy<IServer>(); tbLog.Text += Environment.NewLine + server.Echo("Login may have worked!?");

 

Damit komme ich etwa bis hier.

public ZyanConnection(...)
{...
  // Am Server anmelden
  RemoteComponentFactory.Logon(_sessionID, credentials);
}

Ergebnis ist -  //SocketException - Eine vorhandene Verbindung wurde vom Remotehost geschlossen
Server stack trace:
bei System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
bei System.Runtime.Remoting.Channels.SocketStream.Read(Byte[] buffer, Int32 offset, Int32 size)
bei System.Runtime.Remoting.Channels.SocketHandler.ReadFromSocket(Byte[] buffer, Int32 offset, Int32 count)
bei System.Runtime.Remoting.Channels.SocketHandler.BufferMoreData()  
bei System.Runtime.Remoting.Channels.SocketHandler.Read(Byte[] buffer, Int32 offset, Int32 count)
bei System.Runtime.Remoting.Channels.SocketHandler.ReadAndMatchFourBytes(Byte[] buffer)
bei System.Runtime.Remoting.Channels.Tcp.TcpSocketHandler.ReadAndMatchPreamble()
bei System.Runtime.Remoting.Channels.Tcp.TcpSocketHandler.ReadVersionAndOperation(UInt16& operation)
bei System.Runtime.Remoting.Channels.Tcp.TcpClientSocketHandler.ReadHeaders()
bei System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream)
bei System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)

Was/Warum/Wie ich da etwas falsch mache würde mich dann doch sehr interessieren.

 

2. IAuthenticationProvider - Schnittstelle

Diese versuche ich ja wie gesagt in meiner eigenen Klasse zu bauen. Das sieht auch erstmal gar nicht so schwer aus, nur aus dem Rückgabewert werde ich nicht sonderlich schlau.

public AuthResponseMessage Authenticate(AuthRequestMessage authRequest)
{
  AuthResponseMessage response = new AuthResponseMessage();
  //response.AuthenticatedIdentity = ???!?
  //response.AuthenticatedIdentity = new GenericIdentity("?!?");
            
  if ( Accounts.LogIn( authRequest.Credentials["user"], authRequest.Credentials["password"] ) )           
      response.Success = true;
  return response;
}

 

Wer oder was ist die IIdentity und woher bekomme ich die, wenn ich nicht auf Windows-Nutzer oder Richtlinien etc. zurückgreifen, sondern eine simple Nutzername / Password Authentifizierung bauen will? Dafür habe ich bisher leider auch noch kein Beispiel gefunden.

In froher Hoffnung auf eine hilfreiche Antwort biertrinkend,Luth (2)

Coordinator
Aug 4, 2011 at 7:49 AM
Edited Aug 4, 2011 at 8:00 AM

Hallo Luth2,

Wenn ich es richtig verstanden habe, versuchst Du alles in eine Klasse zu packen. Das wird spätestens, wenn Deine Anwendung größer wird (was früher oder später mit allen
erfolgreichen Anwendungen passiert) unübersichtlich. Ich würde für den Host(Server) und den Authentifizierungsanbieter getrennte Klassen erstellen.

Ein Authentifizierungsanbieter für Deine Accounts-Klasse lässt sich ganz leicht erstellen. Schau:

 

    public class UserAndPasswordAuthProvider : IAuthenticationProvider
    {
        public AuthResponseMessage Authenticate(AuthRequestMessage authRequest)
        {
            if (!authRequest.Credentials.ContainsKey("username"))
                throw new System.Security.SecurityException("Kein Benutzername angegeben.");

            if (!authRequest.Credentials.ContainsKey("password"))
                throw new System.Security.SecurityException("Kein Kennwort angegeben.");

            string userName = (string)authRequest.Credentials["username"];
            string password = (string)authRequest.Credentials["password"];


            if (Accounts.LogIn(userName,password))
            {
                // Erfolgreiche Anmeldung zurückmelden
                return new AuthResponseMessage()
                {
                    Success = true, // Anmeldung erfolgreich
                    AuthenticatedIdentity = new System.Security.Principal.GenericIdentity(userName)
                };
            }

            // Fehlgeschlagene Anmeldung zurückmelden
            return new AuthResponseMessage()
            {
                Success = false, // Anmeldung nicht erfolgreich
                ErrorMessage = "Benutzername oder Password sind ungültig"            
}; } }

 

Für die Konfiguration des Serverprotokolls, sollte das hier sein, was Du suchst:

 

// TCP Duplexkanal auf Port 8080 mit einfacher Benutzer/Password-Athentifizierung (der AuthProvider von oben wird verwendet), ohne Verschlüsselung
var protocol = new TcpDuplexServerProtocolSetup(8080, new UserAndPasswordAuthProvider());
var host=new ZyanComponentHost("Test",protocol);

Du brauchst nicht alle möglichen Werte des Konstruktors ausfüllen. Für gewöhnlich sollten die Standardwerte passen. Ich helfe Dir aber auch gerne bei der Optimierung der Einstellungen für Dein Projekt.
Dafür benötige ich aber genauere Informationen, was Du konkret machen willst. Wichtig ist z.B. ob Du im LAN oder übers Internet kommunizieren willst/musst? Musst Du clientseitige Firewalls überwinden?
Sind Clients teilweise über WLAN angebunden?

Um die Sitzungsverwaltung musst Du Dich nicht selber kümmern. Das tut Zyan automatisch für Dich.
Über ServerSession.CurrentSession bekommst Du - im Serverprozess - jederzeit die Sitzungsinformationen des aufrufenden Clients.
Du kannst auch Sitzungsvariablen lesen/schreiben, wei man es von Webservern her kennt:

 

ServerSession.CurrentSession.SessionVariables["MyVar"] = "Hallo";

 

ClientSeitig würde die passende Konfiguration dazu so aussehen:

// Am Client ebenfalls TCP Duplexkanal ohne Verschlüsselung
var protocol = new TcpDuplexClientProtocolSetup(false);

// Benutzername und Passwort für Anmeldung in Hashtable packen
Hashtable credentials = new Hashtable();
credentials.Add("username","Egon");
credentials.Add("password","geheim");
            
// Verbindung zum Server herstellen
ZyanConnection connection = new ZyanConnection("tcpex://localhost:4711/Test", protocol, credentials, false, true);

Ich hoffe das hilft Dir weiter.

Wenn Du weitere Fragen hast, beantworte ich sie Dir gerne.

Gruß

Rainbird

Aug 4, 2011 at 10:04 AM

Hallo Rainbird,

und danke für die schnelle Antwort. Ich bin gerade auf Arbeit und darf mich mit Delphi rumschlagen :-( ... daher werde ich das erst heute Abend ausprobieren können.

Wenn ich es richtig verstanden habe, versuchst Du alles in eine Klasse zu packen. Das wird spätestens, wenn Deine Anwendung größer wird (was früher oder später mit allen
erfolgreichen Anwendungen passiert) unübersichtlich. Ich würde für den Host(Server) und den Authentifizierungsanbieter getrennte Klassen erstellen.


Jain. Nicht alles - ich wollte lediglich alles was Sessions/Authentifikation/Registrierungsprozess/Serverstatus abfragen ist, in diese Serverklasse stopfen. Für die eigentliche Logik sind andere Komponenten vorgesehen, die jeweils auf einen bestimmten Teilbereich spezialisiert sind. Andererseits dürfte es ja auch nicht schaden, den IAuthenticationProvider woanders zu implementieren. Es war halt einfach praktisch, da die Serverklasse beim Start sowieso alle in der DB vorhandenen Accounts lädt und die ganze Zeit im RAM hält. Das die Anwendung mal erfolgreich wird ist eher zweifelhaft, da es ein Hobbyprojekt ist, das hauptsächlich zum Lernen dient, wie man die komplette Kette Client <> Netz <> Server <> Cache <> Mapper <> Datenbank aufbauen könnte.

Du brauchst nicht alle möglichen Werte des Konstruktors ausfüllen. Für gewöhnlich sollten die Standardwerte passen. Ich helfe Dir aber auch gerne bei der Optimierung der Einstellungen für Dein Projekt.
Dafür benötige ich aber genauere Informationen, was Du konkret machen willst. Wichtig ist z.B. ob Du im LAN oder übers Internet kommunizieren willst/musst? Musst Du clientseitige Firewalls überwinden?
Sind Clients teilweise über WLAN angebunden?

Hm. Server im Internet hinter einer Firewall, Clients irgendwo hinter ihren Firewalls, die über das Internet auf den Server zugreifen. Davon dann möglichst viele gleichzeitig. :D Wenn ich richtig gelesen habe, funktioniert sowas dann mit dem TCPDuplexProtokol am besten und ich kann dann immer noch mit Events rumhantieren - obwohl bei vielen Clients ja Delegaten sinnvoller sein sollen, aber danach frage ich bestimmt später nochmal. ;-) Im Wesentlichen sollen sich die Clients da erst registrieren ( also ohne Authentifizierung erstmal durchkommen oder einen Zweitkanal dafür bereitstellen? ), danach anmelden, dann irgendwelche Funktionen, auf gecachten oder auch frisch aus der DB geholten Daten aufrufen. Der Server selbst wird auch noch zeitgleich auf den Daten arbeiten müssen, die derzeit alle als Objekte in synchronisierten Dictionaries rumliegen.

Um die Sitzungsverwaltung musst Du Dich nicht selber kümmern. Das tut Zyan automatisch für Dich.
Über ServerSession.CurrentSession bekommst Du - im Serverprozess - jederzeit die Sitzungsinformationen des aufrufenden Clients.

Ja, aber wie bekomme ich dann mit, ob Sessions abgelaufen sind oder neu dazukommen, wenn sich Clients beispielsweise für bestimmte Serverevents registriert haben und die Session abläuft oder Verbindung abbricht? Die OnClientLoggedOn / Off Events des ComponentHost feuern bei Erstellen/Abbauen der TCP-Verbindung, Anmelden der Session oder erst bei gelungener Authentifizierung? 

Ich hoffe das hilft Dir weiter.

Das tut es auf jeden Fall. Also schonmal recht vielen Danke dafür!

 

Luth der zweite.

Coordinator
Aug 10, 2011 at 7:05 AM
Edited Aug 10, 2011 at 7:08 AM

Hallo Luth2,

Im Wesentlichen sollen sich die Clients da erst registrieren ( also ohne Authentifizierung erstmal durchkommen oder einen Zweitkanal dafür bereitstellen? ), danach anmelden, dann irgendwelche Funktionen,
auf gecachten oder auch frisch aus der DB geholten Daten aufrufen.

Das halte ich sicherheitstechnisch nicht für empfehlenswert. Die Clients sollten ohne eine gültige Anmeldung definitiv nicht durchkommen. Ich würde auch keinen Zweitkanal für sowas bereitstellen. Warum willst
Du das denn so machen? Gibt es einen bestimmten Grund?

Was ist der Zweck dieses Registrierungsvorgangs vor dem eigentlichen Anmelden mit Benutzername und Passwort?

Ja, aber wie bekomme ich dann mit, ob Sessions abgelaufen sind oder neu dazukommen, wenn sich Clients beispielsweise für bestimmte Serverevents registriert haben und die Session abläuft oder Verbindung
abbricht?

Du musst Dich darum nicht selber kümmern. Eine Sitzung lebt auf jeden Fall so lange wie ihr zugeordneter Client. Jeder Client verlängert automatisch seine Sitzung in einem festgelegten Intervall. Sitzungen laufen
deshalb nicht ab. Eine Sitzung läuft nur dann ab, wenn der Client unerwartet offline geht und sich nicht vorher abmeldet. Dann empfängt der Server ja keine Verlängerungsanfragen mehr und verlängert die Sitzung
deshalb auch nicht weiter. Damit der Speicherplatz einer solchen verwaisten Sitzung wieder frei wird, räumt Zyan regelmäßig verwaiste abgelaufene Sitzungen ab. Es gibt in 95% der Fälle keinen Grund, warum Du
da manuell eingreifen solltest. Aber es ist natürlich möglich. Wenn Du die komplette Kontrolle über die Sitzungsverwaltung haben willst, kannst Du einen eigenen Sitzungsmanager schreiben und diesen beim
ZyanComponentHost-Konstruktor übergeben. Das ist nicht schwierig. Du musst nur von SessionManagerBase erben. Sieh Dir einfach die Klasse InProcSessionManager im Zyan-Quellcode an. Diese
Implementierung eines Sitzungsmanagers wird standardmäßig verwendet, wenn Du nichts anderes angibst.

Hier findest Du eine Übersicht über die Methoden, die Du implementieren musst, wenn Du einen eigenen Sitzungsmanager schreiben willst: http://zyan.codeplex.com/wikipage?title=ISessionManager&referringTitle=Sitzungsverwaltung

Was unerwartete Verbindungsabbrüche angeht, wird es bald ein System geben, diese komfortabel zu behandeln. Siehe http://zyan.codeplex.com/workitem/1093.

Die Registrierung von Clients bei Events von Serverkomponenten hat mit der Sitzungsverwaltung eigtentlich nichts zu tun. Bei Events werden dynamisch erzeugte Interceptor-Objekte als Eventhandler registriert.
Diese halten die Verbindung zum Client und leiten Eventfeuer an den Client weiter. Der Client ordnet die Eventfeuer-Benachrichtigung über einen eindeutigen Korrelationsschlüssel seinen lokalen Komponenten bzw.
deren Membern zu. Die Event-Geschichte würde auch komplett ohne Sitzungsverwaltung funktionieren.

Sitzungen werden primär zur Authentifizierung und für Sitzungsvariablen benötigt.

Die OnClientLoggedOn / Off Events des ComponentHost feuern bei Erstellen/Abbauen der TCP-Verbindung, Anmelden der Session oder erst bei gelungener Authentifizierung?

ClientLoggedOn wird nach erfolgreichem Anmelden eines Benutzers gefuert. ClientLoggedOff wird nach dem Abmelden eines Clients gefeuert.

Oft fühlen sich Entwickler, die es gewohnt sind alles bis ins Detail selbst zu schreiben, durch ein Framework "entmachtet". Das Framework gibt viele Dinge bereits vor und man hat über einige Dinge
zunächst nicht die volle Kontrolle. Bei Zyan ist das aber relativ unbedenklich, da man bei fast allen Features eingreifen und den Standard durch eigene Implementierungen ersetzen kann. Hier einige Beispiele für
solche Erweiterungsmöglichkeiten:

  • Eigene Kanalsenken schreiben (Ermöglicht Einflußnahme auf die Kommunikation und die übertragenen Bytes)
  • Eigene Formatierungssenken schreiben (Ermöglicht die Implementierung eigener Kommunikationsprotokolle auf Anwendungsebene)
  • Eigene Transportkanäle schreiben (Ermöglicht die Nutzung eigener Transportmedien/Protokolle, z.B. wäre ein Transportkanal für SMTP und POP3 denkbar)
  • Eigene ProtocolSetups erstellen (Vorhandene Transportkanäle, Formatierer und Senken völlig frei zusammenstellen und konfigurieren)
  • CallInterceptors schreiben und registrieren (Verhalten bestimmter Remoteaufrufe verändern)
  • Serialisierungshandler schreiben (Ermöglicht benutzerdefinierte Serialisierung für bestimmte Datentypen)
  • Eigene Authentifizierungsanbieter schreiben (Ermöglicht die Implementierung beliebiger Authentifizierungssysteme)
  • Eigene Sitzungsmanager schreiben (Ermöglicht die Implementierung benutzerdefinierter Sitzungsverwaltungssysteme)

Zusätzlich bieten ZyanConnection und ZyanComponentHost noch diverse Ereignisse, die man behandeln kann.

Viele Anwendungsfälle lassen sich aber schon mit den, in Zyan verfügbaren, Standard-Features abdecken.

Aug 10, 2011 at 7:13 PM

Hi Rainbird.

Erstmal danke für die vorherigen Tips, die Umsetzung der Authentifizierung und das konfigurieren des TcpDuplexProtokolls hat schonmal super funktioniert.

Das halte ich sicherheitstechnisch nicht für empfehlenswert. Die Clients sollten ohne eine gültige Anmeldung definitiv nicht durchkommen. Ich würde auch keinen Zweitkanal für sowas bereitstellen. Warum willst
Du das denn so machen? Gibt es einen bestimmten Grund?

Weil die, für die Anmeldung benötigten Daten, ja irgendwie bereitgestellt werden müssen. Und da ich, weil ich keine Lust habe, die manuell zu vergeben, einen anderen "zweiten Kanal" oder ähnliches bräuchte um die Login-Daten zu übermitteln. Ich hab das prinzipiell erstmal ganz einfach gelöst bzw. rausgeschoben, indem ich die Clients, wenn es noch keine gültigen Login-Daten gibt, bei Bedarf eine Registrierungsanforderung für die mitgesendeten Login-Daten mitsenden lasse. Momentan also so:

  1. Prüfen ob das ein gültiges Login ist
  2. Falls nicht, prüfen ob das eine Registrierungsanforderung ist
  3. Falls ja, registerieren
  4. (noch nicht implementiert) Email an Validierungsadresse senden mit Aktivierungscode etc.
  5. Account aktivieren, wenn der Client sich mit gültigem Aktivierungscode meldet - falls nicht, halt immer wieder abweisen
  6. Wenn der Account nach Zeitraum X immer noch nicht aktiviert ist, wieder rauswerfen.

Du musst Dich darum nicht selber kümmern. Eine Sitzung lebt auf jeden Fall so lange wie ihr zugeordneter Client. Jeder Client verlängert automatisch seine Sitzung in einem festgelegten Intervall. Sitzungen laufen
deshalb nicht ab. Eine Sitzung läuft nur dann ab, wenn der Client unerwartet offline geht und sich nicht vorher abmeldet. Dann empfängt der Server ja keine Verlängerungsanfragen mehr und verlängert die Sitzung
deshalb auch nicht weiter. Damit der Speicherplatz einer solchen verwaisten Sitzung wieder frei wird, räumt Zyan regelmäßig verwaiste abgelaufene Sitzungen ab. Es gibt in 95% der Fälle keinen Grund, warum Du
da manuell eingreifen solltest. ...


Hm. Für die Verwaltung der eigentlichen Sitzung gibt es ja die KeepAlive-Optionen. Wenn aber einer ohne Abmeldung offline geht, wie bekomme ich dann irgendwann mit, dass der Server die Sitzung aufräumt? Ich arbeite viel mit gecachten Daten, die, als threadsicheres Singleton, im Speicher gehalten werden und auf die viele Clients gleichzeitig zugreifen sollen. Welche Daten gecacht werden, richtet sich dabei unter anderem danach, welche Clients gerade online sind. Daher wüsste ich halt gerne, wer, wann kommt und wieder geht - auch wenn er sich nicht regulär abgemeldet hat. Wenn ich jetzt nicht ganz falsch liege, ist es mir dann auch egal, ob ich das anhand der Session oder der Verbindung mitbekomme. Ich finds schon jetzt manchmal ärgerlich wenn ich die Connect- und Disconnect-Events mitzähle und meine ClientCount Anzeige dann trotzdem ewig auf 1 stehen bleibt, weil ich den Client per Taskmanager weggeschossen habe. ;-)

Aber es ist natürlich möglich. Wenn Du die komplette Kontrolle über die Sitzungsverwaltung haben willst, kannst Du einen eigenen Sitzungsmanager schreiben und diesen beim
ZyanComponentHost-Konstruktor übergeben.

Ja, das geht gut. Damit hatte ich auch schonmal angefangen - aber dann erstmal liegen lassen, weil ich am Anfang ja gar keine Verbindung zustande bekommen habe.

Was unerwartete Verbindungsabbrüche angeht, wird es bald ein System geben, diese komfortabel zu behandeln. Siehe http://zyan.codeplex.com/workitem/1093.

Das bedeutet, das sowohl Client als auch Server dann Events anbieten könnten, wenn das passiert? Das wäre super. Dann lass ich die Baustelle erstmal offen und schau ob das nicht schon vollkommen ausreicht.

Oft fühlen sich Entwickler, die es gewohnt sind alles bis ins Detail selbst zu schreiben, durch ein Framework "entmachtet". Das Framework gibt viele Dinge bereits vor und man hat über einige Dinge
zunächst nicht die volle Kontrolle.

Tja...bin berufsgeschädigt. Ich hatte ja mal erwähnt, das ich da mit Delphi unterwegs sein darf und da gibt es viele der hier benutzten Dinge nicht, nur auf Umwegen und/oder schon gleich gar nicht in der Anwendung die wir bauen. Ich geh dann auch erstmal nachlesen, was Kanalsenken so sind und machen. :P

Danke nochmal,

Luth

Coordinator
Aug 13, 2011 at 2:40 PM

Hallo Luth,

wenn ich das richtig verstanden habe, möchtest Du ein Registrierungssystem für Benutzer bauen, wie man es von Webshops her kennt. Dafür brauchst Du aber keinen separaten Kanal. Das sollte mit einem selbstgeschriebenen AuthenticationProvider zu schaffen sein. Du musst nur zulassen, dass Anmelung auch ohne Credentials nöglich ist. In dem Fall kannst Du ja eine fest definierte Gast-Identität als "Authentifizierten Benutzer" setzen. Diese Identität hat dann eben nur Rechte für Registrierungsfunktionen, darf sonst aber nichts. Wenn ein Gast-Benutzer sich registriert und anschließend den Aktivierungscode (aus der E-Mail) sendet, bekommt er z.B. seine endgültigen Credentials per Mail zugeschickt.

Das ist auch ganz einfach zu programmieren. Du musst ja nur die Credentials-Hashtable auswerten. Die Name-Wert-Paare der Credentials kannst Du ja frei vergeben. Das muss nicht "Username" und "Passwort" heißen. So können die einzelnen Phasen über Credentials abgebildet werden:

1. Gast-Zugang

Keine Credentials übergeben. Gast-Benutzer ruft Funktion auf, welche eine Liste der benötigten Credentials für die Registrierung (z.B. Stage="regiser", UserName=?, Password=?, MailAddress=?) zurückgibt

2. Registrierung

credentials["Stage"]="register";
credentials["UserName"]="maxmuster";
credentials["Password"]="geheim";
credentials["MailAddress"]=max.muster@test.de";

3. Bestätigung der Registrierung

credentials["Stage"]="activate";
credentials["ActivationCode"]="4711";

4. Richtige Anmeldung

credentials["Stage"]="login";
credentials["UserName"]="maxmuster";
credentials["Password"]="geheim";

Im AuthenticationProvider musst Du so nur zuerst das "Stage" Credential auswerten. Die komplette Benutzerverwaltung könntest Du so über Deinen eigenen AuthenticationProvider steuern. Auch Löschungen, Kennwortänderungen o.Ä. lassen sich so abbilden. Vor allem ist das System leicht erweiterbar. Morgen musst Du vielleicht noch einen Mandantenschlüssel beim Anmelden übertragen.

Das ist natürlich nur einer von vielen Wegen, wie man sowas mit Zyan machen kann. Der Fantasie sind praktisch keine Grenzen gesetzt.

Nur einen zweiten Kanal würde ich dafür nicht einsetzen. Das ist nur unnötiger Aufwand.

Was Du generell selber schreiben musst ist ein System zur Berechtigungsprüfung (Authorisierung). Das ist immer sehr stark von der Anwendung und den Anforderungen abhängig.

Muss/Soll Deine Zyan-Anwendungen eigentlich auch von Delphi aus zugreifbar sein?

Gruß

Rainbird

Aug 15, 2011 at 8:03 AM

Hallo Rainbird,

genau sowas hatte ich eigentlich gemeint, mich aber wohl nicht klar genug ausgedrückt. Momentan habe ich es so ähnlich implementiert, wie du es oben auch beschrieben hast. Ich schick statt den einzelnen Credentials ein Account-Object hin und her, mit einem Kennzeichen, ob dieser nun eingeloggt, registriert oder gelöscht werden soll. Das mit dem "zweiten Kanal" war also nicht auf die Connection oder die Verbindungsart bezogen, sondern auf den abstrakten Vorgang "anmelden, authenifiziert werden, damit arbeiten, ausloggen" ... den ich für nicht registrierte Benutzer ja irgendwie umgehen musste.

Was Delphi angeht, würde ich das derzeit eher verneinen. Das eine ist meine Arbeit und das .net-Zeug mehr so eine Art Bastel- und Weiterbildungsprojekt - schlicht um mal zu sehen, was es alles gibt und wie man sowas machen könnte. Da die Delphi-Software auf Arbeit aber auch seit etwa 10-15 Jahren "reift", wäre da eine Neukonstruktion oder ein Umstieg eigentlich auch mal nötig. Bisher ist das aber noch nicht durch- und umsetzbar. Sollte das irgendwann mal der Fall sein, wäre es ja denkbar Teile der Anwendung in .net zu implementieren und den Rest nach und nach umzuziehen. Allerdings stelle ich mir das auch gar nicht so einfach vor, da ja das Remoting Protokoll in Delphi so nicht vorhanden ist, derzeit alles in nativem Delphi-Code und ungemanagten dlls rumliegt und die Serialisierungen von Objekten bzw. die Objekte selbst sicher völlig anders aussehen. Momentan benutzen wir eine Delphi-Technik namens "DataSnap", die ähnlich .net-Remoting ist - aber nur so halb funktioniert. :D

Coordinator
Aug 15, 2011 at 8:35 PM

Hallo Luth,

.NET bietet hohe Kompatibilität zu COM. Da auch Delphi COM (wird manchmal auch als ActiveX bezeichnet) unterstüzt, ist das der vielversprechendste Ansatz. Für eine Zyan-Applikation würde das bedeuten, dass für die clientseitige API eine COM-Interop-Assembly geschrieben wird. Diese "verpackt" die Funktionalität in COM-Typen. Der Aufwand, sowas zu schreiben, hält sich in Grenzen. Die entfernte Kommunikation würde trotzdem mit .NET Typen und .NET seitiger Serialisierung abgewickelt.

Nur falls es in absehbarer Zeit ernst mit der Delphi-.NET-Integration wird.