Um das grundlegende Konzept von serverseitigem Sitzungs-Caching zu verstehen, implementieren Sie eine kleine Anwendung mit Flask, einem Microframework für die Webentwicklung in Python. Da der Schwerpunkt auf den Konzepten und nicht den Einzelheiten bestimmter Frameworks oder Sprachen liegt, lassen sich die Beispiele auf beliebige Web-Frameworks und Programmiersprachen übertragen.
Für den Einstieg in Flask befolgen Sie die Installationsanweisungen und die Kurzanleitung.
Im Folgenden finden Sie eine sehr einfache Anwendung für die An- und Abmeldung:
syntax: python
import os from flask import Flask, session, redirect, escape, request app = Flask(__name__) app.secret_key = os.environ.get('SECRET_KEY', default=None) @app.route('/') def index(): if 'username' in session: return 'Logged in as %s' % escape(session['username']) return 'You are not logged in' @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect('/') return ''' <form method="post"> <p><input type=text name=username> <p><input type=submit value=Login> </form> ''' @app.route('/logout') def logout(): session.pop('username', None) return redirect('/')
Der Rest der Beispiele basiert auf diesem Snippet. Den Code für alle Beispiele finden Sie in diesem Repository.
Wenn Sie Flask bereits installiert haben und diese Anwendung starten möchten, kopieren Sie den Code in eine Datei namens example-1.py. Danach müssen Sie zwei Umgebungsvariablen exportieren: FLASK_APP sollte auf example-1.py eingestellt sein, SECRET_KEY auf einen zufälligen String, zum Beispiel Y0PJWblKsg1axM4fGW. Hilfe zur Erstellung von Umgebungsvariablen finden Sie in der Kurzanleitung von Flask.
Wenn alles bereit ist, führen Sie diesen Befehl aus:
syntax: shell
$ flask run -h 0.0.0.0 -p 5000 --reload
Rufen Sie dann http://your_flask_endpoint:5000 auf. Dort sollte Ihre Anwendung laufen. Dann müssen Sie your_flask_endpoint mit dem öffentlichen DNS-Namen Ihrer EC2-Instance ersetzen, wie Sie es in den Anforderungen getan haben.
Es sind drei Pfade verfügbar: “/”, “/login” und “/logout”. Rufen Sie alle der Reihe nach auf, um sich mit dem grundlegenden Verhalten vertraut zu machen.
Veranschlagte Zeit für das Modul: 60–90 Minuten
Im Beispiel wird ein Cookie zum Speichern des Benutzernamens verwendet. Beim ersten Aufruf der Anwendung ist kein Benutzername im Sitzungsobjekt gespeichert. Wenn Sie "/login" aufrufen und einen Benutzernamen angeben, wird der Wert in einem signierten Cookie gespeichert und Sie werden zur Startseite weitergeleitet. Beim Aufrufen von "/logout" wird der Benutzername aus der Sitzung gelöscht und Sie befinden sich wieder am Ausgangspunkt.
Sie werden diese einfache Anwendung um serverseitige Sitzungen erweitern. Zunächst überprüfen wir aber Ihre Verbindung zu Redis.
Der in den Beispielen genannte Redis-Endpunkt bezieht sich immer auf den Hostnamen Ihres primären Endpunkts.
syntax: shell
$ export REDIS_URL="redis://your_redis_endpoint:6379"
syntax: shell
$ python
syntax: python
>>> import redis >>> client = redis.Redis.from_url('redis://your_redis_endpoint:6379') >>> client.ping() **True**
Wenn der Befehl nicht ausgeführt wird, wird der Prozess aufgrund der Einstellungen der Sicherheitsgruppe blockiert. Überprüfen Sie, ob Ihre EC2-Instance auf die Sicherheitsgruppe zugreifen kann, die Ihrer ElastiCache-Instance zugewiesen ist. Beispiel: Angenommen, Ihre EC2-Instance wurde der Standard-Sicherheitsgruppe zugewiesen. Sie können nun die Einstellungen für die Sicherheitsgruppe Ihrer Amazon ElastiCache-Instance anpassen und eine benutzerdefinierte TCP-Regel hinzufügen, mit der Verbindungen von jeder Instance in der Standard-Sicherheitsgruppe über Port 6379 zugelassen werden.
In Source können Sie dazu den Namen der Sicherheitsgruppe eingeben und anschließend auf die ID der betreffenden Sicherheitsgruppe klicken. Weitere Informationen zu Sicherheitsgruppen finden Sie in der Dokumentation oder im Referenzleitfaden für Sicherheitsgruppenregeln.
Kehren wir zu unserem Beispiel zurück. Wir nehmen jetzt einige kleine Änderungen vor, durch die Sie Sitzungsdaten in Redis speichern können. Hier ist das zweite Beispiel mit diesen Änderungen:
syntax: python
import os import redis from flask import Flask, session, redirect, escape, request app = Flask(__name__) app.secret_key = os.environ.get('SECRET_KEY', default=None) # BEGIN NEW CODE - PART 1 # REDIS_URL = os.environ.get('REDIS_URL') store = redis.Redis.from_url(REDIS_URL) # END NEW CODE - PART 1 # @app.route('/') def index(): if 'username' in session: # BEGIN NEW CODE - PART 2 # username = escape(session['username']) visits = store.hincrby(username, 'visits', 1) return ''' Logged in as {0}.<br> Visits: {1} '''.format(username, visits) # END NEW CODE - PART 2 # return 'You are not logged in' @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect('/') return ''' <form method="post"> <p><input type=text name=username> <p><input type=submit value=Login> </form>''' @app.route('/logout') def logout(): session.pop('username', None) return redirect('/')
Nun wurde Redis importiert und initialisiert, und der Index übernimmt die Inkrementierung eines Zählers und zeigt diesen dem Benutzer an.
Hinweis: Der zur Inkrementierung des Zählers verwendete Redis-Befehl lautet HINCRBY. Das liegt daran, dass Sie einen Redis-Hash für jede Benutzersitzung verwenden.
Jetzt stellen Sie für die serverseitige Sitzung eine Time To Live (TTL) ein. Es handelt sich lediglich um eine weitere Codezeile und dieses Snippet enthält nur den Pfad /.
syntax: python
... @app.route('/') def index(): if 'username' in session: username = escape(session['username']) visits = store.hincrby(username, 'visits', 1) # BEGIN NEW CODE # store.expire(username, 10) # END NEW CODE # return ''' Logged in as {0}.<br> Visits: {1} '''.format(username, visits) return 'You are not logged in' ...
Der Schlüssel, in dem die Sitzung gespeichert wird, läuft in 10 Sekunden ab. Die TTL ist sehr kurz und nur für dieses Beispiel brauchbar. Wenn Sie die Anwendung jetzt ausführen, werden Sie sehen, wie der Aufruf den Index-Zähler aktualisiert. Laufen die 10 Sekunden ohne einen Aufruf ab, wird der Zähler bei der nächsten Aktualisierung auf 1 zurückgesetzt.
Dieses kurze Beispiel eignet sich zum Erlernen der Grundlagen serverseitiger Sitzungen, aber in der Praxis würden Sie anders verfahren: Anstatt den Benutzernamen zu speichern, wird nach der Authentifizierung des Benutzers ein Token erzeugt und gespeichert. Dieses Token wird von dem Redis-Schlüssel repräsentiert, unter dem alle serverseitigen Sitzungsdaten gespeichert werden. Es bietet sich auch an, das hier beschriebene Verhalten in Teilen zu abstrahieren, damit jeder Zugriff auf die serverseitige Sitzung die TTL ohne Ihr Eingreifen aktualisiert. In diesem Repository finden Sie ein Beispiel mit einer SessionStore-Klasse, die dieses Verhalten abstrahiert.