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('/')
$ flask run -h 0.0.0.0 -p 5000 --reload
接著前往 http://your_flask_endpoint:5000,在這裡您應會看到應用程式正在執行。您必須將 your_flask_endpoint 取代為 EC2 執行個體的公有 DNS 名稱,如同您在「要求」中所做的一樣。
有三個可用的路由:「/」、「/login」及「/logout」。依次瀏覽,您就能更加了解基本行為。
完成單元的時間︰60 – 90 分鐘
範例使用 Cookie 來儲存使用者名稱。初次瀏覽應用程式時,工作階段物件中沒有儲存使用者名稱。前往「/login」並提供使用者名稱時,會將值儲存在簽署的 Cookie 中,並且您將重新導向至首頁。接著,如果您前往「/logout」,使用者名稱會從工作階段中移除,您會回到開始的位置。
您將使用伺服器端工作階段延伸這個基本應用程式,但是請先確認您可以連接至 Redis。
在範例中,於每次提到 Redis 端點時,應使用主要端點的主機名稱。
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**
如果命令停止回應,則表示您已遭到「安全群組」設定封鎖。驗證您的 EC2 執行個體是否可存取分配到 ElastiCache 執行個體的安全群組。例如,假設您的 EC2 執行個體被分配到預設的安全群組。您現在可以修改 Amazon ElastiCache 執行個體的安全群組,並新增自訂的 TCP 規則,從而允許來自預設安全群組中的任何執行個體對連接埠 6379 進行連接:
返回範例。現在您將引入部分的小型變更,以便讓您在 Redis 中儲存工作階段資料。這是變更的第二個範例:
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('/')
現在 Redis 已完成匯入與初始化,並且索引負責新增計數器,並向使用者顯示。
請注意,您用來新增計數器的 Redis 命令是 HINCRBY。這是因為您將 Redis 雜湊用於每個使用者的工作階段。
現在您將為伺服器端工作階段設定存留時間 (TTL)。這僅是一行額外的程式碼,而且這個片段僅會包含 / 路由。
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' ...
儲存工作階段的金鑰將在 10 秒後過期。這個 TTL 非常簡短,僅適用於本範例。如果現在執行應用程式,您會看到瀏覽索引如何更新瀏覽計數器,但是如果您在 10 秒內未瀏覽該頁面,下次重新整理時計數器會回到 1。
這個簡短的範例足以學習伺服器端工作階段的基本情況,但在實際情況下有些許差異:使用者通過驗證時,會產生並儲存字符,而不是儲存使用者名稱。該字符代表 Redis 金鑰,所有伺服器端工作階段資料將儲存在此。您可能希望擷取此處顯示的部分行為,以便任何伺服器端工作階段的存取都會重新整理 TTL,而無須您進行操作。您可在儲存庫中查看擷取行為的 SessionStore 類別範例。