Wie realisiert man einen Login über RESTful Web Services

JustVoodoo

Cadet 2nd Year
Registriert
Aug. 2010
Beiträge
31
Hallo zusammen,

ich brauche eure Hilfe um ein kleines Projekt vorran zu bringen, denn da weiß ich im Moment nicht weiter. Und zwar versuche ich gerade eine WebApp für ein Haushaltsbuch zu schreiben, so dass man erstmal über den Browser, später übers Smarthphone, sich mit Namen und Passwort anmelden kann und dann seine eigenen Einträge (Wann habe ich was und für wieviel gekauft) lesen/erstellen/editieren kann.

Dazu möchte ich folgendes benutzen:
  • JSP für die WebApp
  • MySQL für die Speicherung von Usern und Einträgen
  • RESTful Web Services (Jersey) um auf die Datenbank zuzugreifen

Das Problem ist, dass ich zu viele unterschiedliche und nicht zusammenhängende Tutorials, Foreneinträge und andere Dinge gelesen habe ich jetzt recht verwirrt bin, wie ich das Ganze eigentlich umsetzen soll...

Bisher kenne ich mich eigentlich nur mit Objektorientierter Programmierung (Java) und ein bischen SOAP aus. WebApplications habe ich bisher auch nur mit ZKoss geschrieben und wollte mich mal an JSP wagen. Mit RESTful WS habe ich erst vor kurzem angefangen und habe noch einige Verständnisprobleme mit dem Resourcen orientierten Ansatz.


Ich stelle hier einfach mal meine "Lösung" vor, woran ich gerade arbeite, aber ich habe das Gefühl, dass ich die Technologien nicht so einsetze, wie man es eigentlich sollte, ganz besonders den REST-Teil.

---

Ich bin soweit, dass ich über einfache JSPs, bzw. unter Verwendung der REST Web Services, die User und Einträge verwalten kann. Allerdings kann jeder mit einem Browser auf alle Resourcen (Einträge und User) zugreifen, ohne dass ein Login erforderlich wäre. Also wenn man z.B. .../eintrag/1 eingibt, bekommt man den entsprechenden Datensatz aus der DB zurück, egal wer die Daten anfordert.

Jetzt habe ich gelesen, dass man mittels HTTP (BASIC) Authentication den Zugriff auf die Resourcen des Web Services einschränken kann. Dabei gibt es aber das Problem, dass dann potentielle Benutzer in die Konfigurationsdaei des Web Servers (Tomcat 7.x) eingetragen werden müssten. Das will ich eigentlich nicht, denn die sollten in der DB gespeichert werden.

Also habe ich mich dazu entschlossen, dass sich nur die WebApp gegenüber dem Server authentisieren kann, so dass ich nur einen User im Tomcat Server registrieren muss. Somit kann schon mal niemand über den Browser o.ä. auf die Resourcen des Web Services zugreifen. Bleibt nur das Problem, dass sich jetzt ein User mit Namen und Passwort noch über die WebApp anmelden können muss, so dass er nur seine eigenen Einträge angezeigt bekommt.

Das wollte ich wie folgt machen:
  1. In der WebApp gibt man Name und Passwort ein
  2. Die WebApp führt daraufhin ein HTTP Request [GET .../user/login?username=x&password=y] (was aber wohl nicht sehr RESTful ist oder?) und bekommt die ID des Nutzers zurück *
  3. Die WebApp soll die ID dann für alle weiteren Anfragen benutzen, um nur Einträge des entsprechenden Users anzuzeigen


* Dabei sind x = MD5(name), y=MD5(password), was aber wohl keine Replay Attacken verhindern kann? Im Grunde würde das wohl auch gar nichts bringen, oder? Denn wenn jemand den Request abfängt, dann bekommt er ja in jedem Fall ein gültiges Paar aus Username und Passwort... Hilft da vielleicht die Verschlüsselung mit SSL??


Wenn die WebApp dann die ID hat, kann sie z.B. mittels GET .../eintrag/user/33 alle Einträge des Users mit der ID 33 anfordern.


Alles zusammen bin ich der Meinung, dass das was ich da mache schlicht "Murks" ist und ich habe keine Ahnung in wie es richtig gemacht wird.

Offene Fragen sind noch:
LIST]
[*]Kann ich für mein login-Problem accessTokens Verwenden und wenn ja wie?
[*]Sollte man auf jeden Fall SSL/TLS verwenden, oder gibt es auch Ansätze die ohne auskommen? Es muss auch nicht ultra sicher sein, sind ja keine Bankgeheimnisse, die ich da speichern will.
[/LIST]


Ich suche hier also auch keine fertige Lösung mit Code, sondern den Weg, wie es (heutzutage) richtig gemacht wird.

Schon mal Danke im Voraus.
 
Du kannst doch per Post Daten senden, dadurch eine Session auf dem Server eröffnen. Auf Clientseite gibt es ein entsprechendes Cookie, das die Daten (Session ID) automatisch bei jeder folgenden Anfrage mitsendet. D.h. bestimmte REST Anfragen funktionieren nur mit korrekt gesetztem Cookie auf Clientseite, dessen Session ID auf Serverseite vorhanden und gültig sein muss.
 
Puh, ganz schön langer Text für solche Temperaturen. :D Ein paar Empfehlungen kann ich jedoch machen.

Da du ja ohnehin auf JSPs aus bist kann ich zu Spring MVC raten mit JSP view. Zudem ist Spring auch super aufgestellt, um mit wenigen Handgriffen REST-Apis zu basteln.

Und für die Authentifizierung rate ich zu OAuth2. Habe ich für unser Produktivsystem gemäß RFC (sieht auf den ersten Blick schlimmer aus als es ist, lesen lohnt sich) implementiert und läuft wie eine Eins. Wir haben darüber einen externen Partner angebunden, der ebenfalls auf einen REST-Service zugreift. Daten werden dabei natürlich per POST übertragen, sonst hast du den ganzen Salat in den access logs deines Webservers stehen. HTTPs ist klar.
Mit OAuth organisierst du quasi eine initiale Authentifizierung und Authorisierung (gibt verschiedene Möglichkeiten im Standard) und wenn der Client dann erstmal authorisiert ist (dann hat er einen sog. access token), kann er anhand seiner client id, seines client secrets und dieses zeitlich limitierten tokens deine services nutzen. Er sendet den ganzen Kram dann mit jedem Request und du validierst das jedes Mal serverseitig.

P.S.: MD5 ist pfui. Zieh dir z.B. apache commons codec ins Projekt und hashe mit SHA256 oder so. Da du ja sicher keine hohe Last hast kannst du auch direkt SHA512 nehmen. Individuell salten nicht vergessen.
 
Zuletzt bearbeitet:
JustVoodoo schrieb:
Offene Fragen sind noch:
LIST]
[*]Kann ich für mein login-Problem accessTokens Verwenden und wenn ja wie?
[*]Sollte man auf jeden Fall SSL/TLS verwenden, oder gibt es auch Ansätze die ohne auskommen? Es muss auch nicht ultra sicher sein, sind ja keine Bankgeheimnisse, die ich da speichern will.
[/LIST]

Du benutzt bei einer REST Anwendung keinen Access Token. Die beiden letzten Buchstaben von REST stehen für Stateless Transfer, du wirst also niemals einen Zustand oder besser gesagt eine Session auf dem Server aufbauen. Jegliche Identifizierung bei REST erfolgt durch Daten, die du bei jeder Anfrage mitsendest und auf dem Server ohne größeren Aufwand - und vor allem ohne den Overhead einer Session! - überprüfen kannst.

Wie du das genau regelst sei dir überlassen, in der Regel wird bei diesem Verfahren der Anfragestring (z.B. "GET /pfad/der/anfrage/1") mit einem Private Key signiert und dann inklusive Public Key als Identifizierung im Header der Anfrage an den Server geschickt. Der Server kennt deinen Public Key und kann mit diesem entsprechend deine Rechte bestimmen und wird eine passende Antwort schicken, falls der Anfragestring richtig signiert wurde. Die Sicherheit ist dadurch gegeben, dass hier nur eine signierte Nachricht und keine Passwörter oder kopierbare Hashes über die Leitung schickst. Übrigens ist HTTPS in so einem Fall ausnahmslos zu empfehlen. Auch wenn dein signierter String im ersten Moment sicher aussieht, könnte ein Angreifer die gleiche Anfrage einfach nochmal senden und so zumindest den Zugriff auf einen Teil der Daten erlangen. Das könnte man durch einen Timestamp in der Signatur zwar eindämmen, aber nicht vollkommen verhindern. Benutze also bitte eine sichere Übertragung! Es gibt schon genug schlecht programmierten Müll auf dieser Welt.

Du kannst stateless übrigens auch so sehen, dass jede Anfrage in sich geschlossen sein muss und zwischen den Anfragen keine Beziehungen (in Form einer Session) bestehen dürfen. Am besten mal nach Lektüre zur Definition dieses Begriffs suchen, gibt es zu Hauf bei Google und Co. Und lies die am besten mehrere durch, manche haben leider das Paradigma nicht verstanden und versuchen Sessions mit einzubauen, was absolut falsch ist und genau der Defnition widerspricht.
 
Zurück
Oben