7. Persistenz, Autorisierung, Cookies
7.3 Ein einfacher Messageboard-Server mit Login-Funktion
Paradebeispiel für eine Anwendung von Cookies ist, dass der Server erkennt, ob der Client sich überhaupt angemeldet hat. Beispielsweise könnte der Server dem Client beim Login ein Cookie setzen von der Formsession_token = 134102381929836
und
sich serverseitig eine Liste aller gültigen Session-Tokens speichern (zusammen mit einem Dictionary,
welcher
Token zu welchem User gehört). Nur Clients, die als Cookie einen gültigen Session-Token vorweisen
können,
werden bedient. Alle anderen werden zur Login-Seite weitergeleitet.
Die Code-Beispiele, die ich im folgenden verwende, bauen auf
dem Blogpost Understanding
Cookies and Implementing them in Node.js
von Catherine
Macharia auf.
Als erstes können Sie sich hier ein "Skelett" runterladen:
12-my-login-server-no-functionality.zip.
Starten Sie den Server mit
npm run dev
Falls das fehlschlägt, müssen Sie eventuell das Projekt "per Hand aufsetzen", wie im Blogpost beschrieben. Wenn Sie gerade im Kurs sind, lassen Sie es mich bitte wissen. Das Projekt besteht aus vier Views: home, login, register und main. Ich habe hier schematisch dargestellt, wie der Navigationsfluss zwischen diesen vier Views aussieht:
Im View main.ejs
können Sie Nachrichten posten, die dann öffentlich
sichtbar sind (einfach, damit irgendeine Form von Funktionalität existiert).
main.ejs
zu laden
oder einen Beitrag zu posten, soll der Server überprüfen, ob
Benutzername und Session-ID stimmen.
Das Input-Feld für den Benutzernamen im View main.ejs
kann jetzt wegfallen.
Bei Logout soll das Cookie für den betreffenden Benutzer gelöscht werden.
Zur Erinnering:- So können Sie serverseitig einen Cookie-Eintrag setzen:
app.post("/process_login", (req, res) => { ... res.cookie("session_id", session_id); ... }
app.get("/main", (req, res) => { // get the username let username = req.cookies.username; ... }
app.get("/logout", (req, res) => { res.clearCookie("session_id"); ... }
Meine Implementierung
Meine Implementierung finden Sie unter
13-login-server.zip.
Entzippen Sie ihn, gehen in das Verzeichnis
und starten Sie den Server per npm run dev
. Der Server bietet folgende
Endpoints an:
-
GET /
schaut, ob Sie bereits eingeloggt sind. Falls ja, schickt es Sie zum Main-View (wo Sie alle Beiträge lesen und einen neuen schreiben können); wenn nein, dann schickt Sie zum Startbildschirm. Beim Startbildschirm können Sie zwischen "create account" und "login" wählen. -
GET /register
schickt Sie zum Registrierungs-Formular. -
POST /process_create_new_account
überprüft die Daten des Registrierungsformulars, schaut zum Beispiel, ob der Username bereits existiert etc. und leitet Sie dann zum Main-View weiter oder mit einer Fehlermeldung wieder zurück zum Hauptbildschirm. -
GET /login
schickt Sie zum Login-Bildschirm. -
POST /process_login
schaut, ob die übermittelten Daten (username und password) mit der "Datenbank" übereinstimmen. Falls ja, setzt der Server relevante Cookies (username
undsession_id
) und leitet Sie zum Main-View weiter; falls nein, dann werden Sie mit einer Fehlermeldung zum Login-Bildschirm geschickt. -
GET /logout
: der Server löscht die Cookies und schickt Sie zum Login-Bildschirm zurück. -
GET /main
schickt Sie zur Hauptseite. Dort gibt es ein Textfeld für die neue Nachricht und eine Tabelle mit allen bisherigen Chat-Nachrichten. Die Tabelle ist erst einmal leer. -
GET /get-messages
: der Server schickt eine Liste von Nachrichten (im Json-Format). -
POST /add-message
: der Server fügt der Liste von Nachrichten die neue Nachricht hinzu und leitet Sie wieder zum Main-View weiter.
Bei den letzten drei Endpoints (/main
, /get-messages
und
/add-message
) überprüft der Server, ob die im Requeste mitgelieferten
Cookies "stimmen", ob also die Werte username
und session_id
im Cookie vorhanden sind, und falls ja, ob die session_id
mit der
übereinstimmt, die sich der Server lokal im Arbeitsspeicher für diesen
username
gemerkt hat. Stimmt das Cookie nicht, wird der Nutzer
mit einer Fehlermeldung wieder zum Login-Bildschirm zurückgeschickt.
Es gibt bestimmt ausgefeilte Weisen, dieses Verhalten formalisiert darzustellen.
Damit kenne ich mich allerdings nicht aus. Daher hier meine selbst ausgedachte
Darstellung:
Der Bereich in der grauen Wolke rechts ist der "geschützte" Bereich, der nur dann betreten / genutzt werden kann, wenn der Browser das richtige Cookie geschickt hat.
Client-seitig müssen Sie den Knopf refresh message klicken, damit neue Nachrichten
angezeigt werden (ich habe aus Bequemlichkeit auf Polling und Websockets verzichtet). Der
Knopfdruck
ruft die Funktion refreshMessages()
auf, der per Ajax die Liste von Nachrichten
vom Server anfordert und diese dann in der Tabelle anzeigt. Beim Laden der Seite wird
auch schon einmal refreshMessages()
aufgerufen.
Der Server überprüft dabei natürlich immer, ob die im Cookie enthalteten Werte für
Benutzername und Session-ID zusammenpassen).
"Hacken" Sie ihn. Das heißt, posten Sie auf dem
schwarzen Brett im View main.ejs
etwas unter
meinem Benutzernamen. "Mein" Benutzername ist der, den ich im Kurs
vor Ihren Augen neu anlegen werde.
Hier nochmal zur Übersicht:
- 193.174.103.62:4012, das Skelett ohne jede Autorisierung
- 193.174.103.62:4014, meine Implementierung mit Autorisierung und Polling.