# Authentifizierung



## Mat00 (9. Nov 2009)

Hallo!

Ich hätte eine client/server authentifizierungsfrage!
und zwar bin ich zur Zeit dabei ein standartisiertes login zu schreiben dass in vielen zukünftigen anwendungen in einsatz kommen soll.

es verwendet kerberos, clientseitig wird also ein service-ticket vom kerberos KDC beantragt und an den server-teil geschickt, dort wird es entschlüsselt, der username entnommen und für eine ldap abfrage benutzt (um festzustellen ob der user in einer bestimmten gruppe ist in der er sein muss um zugriff zu erhalten)

die idee dieses server packages ist im prinzip dass die eigentlichen server in zukunft dieses "authenticationServer-package" in einem seperaten thread starten und alle authentifizierungen darüber abhandeln lassen

ich schicke zur zeit dem client dann die entsprechende antwort zurück... aber jetzt denk ich nochmal ein bißchen über security nach, das alleine würde ja nicht reichen, ein nachgebauter client könnte das ja einfach ignorieren und sich trotzdem zum eigentlichen server verbinden!

irgendwie muss ich diese information (wer korrekt authentifiziert wurde) also serverseitig "mitschleifen", d.h. wenn der user jetzt den eigentlichen server kontaktiert muss ich diese information irgendwie verwenden um zu verhindern dass ein gefälschter client zugreifen kann ("dem client kann man nicht trauen")

hat da irgendjemand eine idee für mich? hab schon überlegt den socket einfach weiterzuleiten, aber das find ich vielleicht doch nicht sogut, die meisten anwendungen werden ja höchstwahrscheinlich auch rmi verwenden wollen und da hilft mir der bereits geöffnete socket wahrscheinlich nicht viel.

wie würdet ihr das lösen?

liebe grüße


----------



## tuxedo (9. Nov 2009)

Na bei RMI ist es recht einfach: 

Der Client holt sich das Remote-Objekt vom Server, welches als Methode nur "login(...)" kennt.

Ist der Login korrekt, so ist der Rückgabewert von "login(...)" das "richtige" Remote-Objekt das alle Methoden enthält die zur Benutzergruppe/Rolle/.. passen.

Ist der Login falsch kommt ne Exception oder ne entsprechende "null" Antwort statt dem Remote-Objekt.

- Alex


----------



## Empire Phoenix (11. Nov 2009)

Die Ip adresse cachen und die dazugehören Berechtigungen, evtl den authentifizierungs socket beibehalten, und alle X minuten feststellen ob der Client noch vorhanden ist (Timeout, Router reconnect, sonst wäre eine Authentifizierung ja ewig gültig). In den anderen Programmen bei neuen sockets überprüfen ob die Ip adresse im cache ist und die notwendigen Berechtigungen hat.

Hat den Vorteil das es sich bei allen Ip basieren Protokollen nutzen lässt egal ob RMI,TCP oder UDP. Hat allerdings Probleme mit NAT's weil es dann jedem Teilnehmer die freigabe geben würde.


----------



## Mat00 (11. Nov 2009)

also ich glaube ich werde es jetzt so machen:
die clients schicken alle _x_ sekunden ein is-alive paket (UDP) an den server und wenn seit dem letzten paket von einem client _x+toleranz_ sekunden vergangen sind wird der client (bzw. dessen ip) wieder von der accept-liste genommen

meint ihr ist das in ordnung?

also wenn ich das jetzt richtig verstehe müssten dann alle anwendungen die dieses loginpackage verwenden im endeffekt nurnoch beim herstellen einer neuen verbindung nachschauen ob die IP des clients gerade in der accept-liste ist, richtig?

hm das mit NATs muss ich mir noch überlegen

vielen dank für die tolle hilfe!!


----------



## FArt (11. Nov 2009)

Tipp:
Das Rad heißt JAAS und SPNEGO.


----------



## Mat00 (11. Nov 2009)

jaas und gss verwende ich ja schon. danke für den tip mit SPNEGO, kannte ich nicht und werds mir bei gelegenheit genauer ansehen!
aber was ich jetzt so darüber gelesen habe ist das im prinzip auch "nur" für authentifizierung und authorisierung (bzw. macht diese generisch), aber da liegt nicht mein problem, ich bin mit meiner aktuellen implementierung (mit kerberos) eigentlich sehr zufrieden!

mein problem ist einfach dass ich die gewonnenen information aus meinem loginpackage am eigentlichen server verwenden können muss ohne die client-server kommunikationsart zu kennen! (d.h. remote objects fallen weg, einfach den socket weiterreichen und über den kommunizieren ebenso, usw.)

darum gefällt mir bis jetzt die idee mit IP-adressen cachen sehr gut, es gibt dann sozusagen eine "isAllowedList". wenn jemand erfolgreich authentifiziert und authorisiert wurde wird er (z.b. mit username und ip) in dieser liste abgespeichert. falls nun jemand auf den server zugreifen will kann er das nur wenn er in dieser liste steht (d.h. erfolgreich authentifiziert wurde)

weitere vorschläge sind gerne willkommen!

bei dem vorschlag bleiben dann im prinzip noch 2 offene fragen
a) wann werden die user wieder aus der liste entfernt? meine ideen wären entweder einfach mittels 2stunden timer(eher schlecht) oder eben über is-alive-packete (oder findet ihr das nicht sinnvoll)

b) an welcher stelle am server-code würde ich diese information dann abfragen? bei jeder aktion wäre overkill, also wäre es mir am liebsten beim verbindungsaufbau
falls ich über sockets kommuniziere ist es leicht, einfach beim/nach dem accept die liste abfragen! aber wie würde ich das bei RMI machen? ich wüsste serverseitig keine stelle im code an der der verbinungsaufbau explizit stattfindet, das ist ja im prinzip alles "RMI-voodoo", was kann man da machen?


----------



## tuxedo (12. Nov 2009)

Naja. Ich persönlich finde das etwas schräg... Welcher Schwierigkeitsstufe soll diese Authentifizierung denn gewachsen sein wenn da einfach die IP gecached wird und hier und da noch ein KeepAlive Paket komm um den Purge-Timer zurückzusetzen?

Mir wäre das irgendwie zu unsicher. Theoretisch könnte ja die Clientanwendung, die momentan als Benutzer A authentifiziert ist gekillt werden und dann mit Benutzer B neu gestartet werden. Wenn dann immernoch KeepAlive Pakete eintreffen wäre Benutzer B mit den Rechten von A unterwegs. 

Wenn man unbedingt die Methodik beibehalten will, das ganze aber besser absichern will, dann wirds denke ich auf KeepAlive-Paket-Ebene recht schnell komplex.

Ich für meinen Teil würde eine Authentifizierung auf Socketebene, über die Client und Server miteinander kommunizieren, bevorzugen (also nix parallel, daneben gesetztes). 

- Alex


----------



## Mat00 (13. Nov 2009)

hm stimmt, hab das nicht so richtig durchdacht glaub ich.. ich dachte ich packe in das package einfach den usernamen ein, aber das wäre auch schwachsinn, weil wenn das unverschlüsselt ist kann jeder hans-huber einfach nen anderen usernamen in das package schreiben und ab gehts und wenn ich das vorher verschlüsseln würde wäre es serverseitig bei mehreren clients ein hoher rechenaufwand das jedesmal wieder zu entschlüsseln und das alle paar sekunden pro client usw. .. nene das geht wohl doch nicht!
ist gut mit jemandem drüber reden zu können, wenn man es mal so richtig ausformuliert kommt man doch auch auf einige sachen drauf + 5 gehirne denken mehr als 1 

wie gesagt, am liebesten wäre mir sowas: authentifizierung über einen socket und der wird anschließend einfach weiter verwendet für die kommunikation!
das wäre auch kein problem wenn die anwendung auch tatsächlich über sockets kommuniziert, aber was ist wenn ich nun RMI verwenden will?

vl mach ich mir auch einfach zuviele gedanken 
ich könnte ja theoretisch beides machen:
a) den socket weiterreichen im falle von socket kommunikation
b) ein rmi remote object zurückgeben im falle von rmi (wobei ich mir das wohl noch genauer ansehen muss, hab das nicht 100% verstanden was du dazu geschrieben hast)
da ich mal stark davon ausgehe dass ein server nur eine einzige kommunikationsart zwischen server und client verwendet wird würde ich das ganze über ein property file steuren

meint ihr das ist sinnvoll?


----------



## tuxedo (13. Nov 2009)

Mal davon abgesehen dass du das Rad scheinbar wirklich nochmal neu erfinden willst:

Bei RMI kann man ne Socket-Factory angeben. Damit kann man die Sockets etwas parametrieren. Ob man RMI damit aber schon laufende Sockets unterschieben kann bezweifle ich noch etwas... Afaik macht RMI da was es will und hält nicht eine einzige Socketverbindung dauerhaft und konstant offen. Bei Bedarf (wie auch immer der aussehen mag) werden Socketverbindungen zugemacht und neue geöffnet. 

Das Prinzip von "Ich öffne einmal einen Socket und kommuniziere bis zum Programmende darüber" gibt es bei RMI soweit ich weiß gar nicht. Sobald Callback-Objekte ins Spiel kommen dreht sich der Spieß sowieso etwas um: Der Server baut da eine Socketverbindung zum Client auf! 

Eine generelle "Authentifizierung über Sockets, egal woher sie kommen und nahtlose Integration" wird wohl nicht so einfach zu machen sein. 

- Alex


----------



## Mat00 (13. Nov 2009)

naja ich möchte nicht zwangsläufig irgendwas neu erfinden und ich kann mir auch gut vorstellen dass ich nicht der erste bin der dieses "problem" hat, hab auch viel dazu nach gelesen aber irgendwie keine befriedigende lösung gefunden

hm ich glaube du hast recht.. das package so flexibel und trotzdem noch nahtlos integrierbar zu machen wird wahrscheinlich leider unmöglich sein
gefällt mir nicht, aber ich glaube ich werde einfach die ganze idee verwerfen und alles was über die authentifzierung hinausgeht direkt in den enstprechenden anwendungen (und nicht in meinem login-package) lösen müssen!

danke auf jeden fall!


----------



## tuxedo (13. Nov 2009)

Na na na.. Nicht gleich so negativ...

Wie wär's denn mit tunneln?

Du könntest einen Tunnel basteln der andere TCP-Protokolle transportieren kann. Und wenn du diesen Tunnel nun mit einer schicken authentifizierung versiehst müsste das gehen. Vorrausgesetzt man schafft es andere Protokolle auf solch einen Tunnel verbinden zu lassen. Evtl. könnte das sogar mit RMI gehen?!

- Alex


----------



## FArt (13. Nov 2009)

Mat00 hat gesagt.:


> hm ich glaube du hast recht.. das package so flexibel und trotzdem noch nahtlos integrierbar zu machen wird wahrscheinlich leider unmöglich sein


Das haben andere auch schon geschafft und dazu einen Standard geschaffen.



Mat00 hat gesagt.:


> gefällt mir nicht, aber ich glaube ich werde einfach die ganze idee verwerfen und alles was über die authentifzierung hinausgeht direkt in den enstprechenden anwendungen (und nicht in meinem login-package) lösen müssen!


Mir auch nicht. Verwende JAAS.

Ich denke mal, du hast zwar viel gelesen, aber immer im Hinblick darauf, dass du alles selber machen willst. Lies dich mal genau in JAAS ein und du wirst feststellen, das Grundgerüst ist fertig und du musst (wenn überhaupt) nur noch Details implementieren.

JAAS Reference Guide
JDK 6 Security-related APIs & Developer Guides -- from Sun Microsystems

Interessant könnte auch das hier sein, denn Spring ist auch ein netter Helfer:
Spring Security Kerberos/SPNEGO Extension | Mike Wiesner - IT-Security, Spring, Acegi

Noch mal: dein Ansatz ist falsch. Öffne dich und du wirst sehen, dass du auf dem falschen Dampfer warst.


----------

