將Session 資料存入資料庫 — 使用 Flask-Session套件

Pei Cheng
PyLadies Taiwan
Published in
7 min readFeb 4, 2018

Flask Web 開發實戰》第四次活動開始介紹如何製作部落格,首先第一步是介紹如何製作會員管理的登入、註冊和驗證等功能,使用 Flask-login 套件來執行相關功能。其中 Flask-login 預設是將 user id 存入 session,而 Flask 預設是將 session 資料加密後存入 cookie 中 (關於 cookiesession 之間的關係請參考第二次活動內容)。實務上,如網站有多個子系統 (可能有不同的 domain)需要共用使用者資料時,存在 cookie 裡便不符合使用需求。因此有人提出將 session 存入資料庫(如 Redis) ,再根據需要存取。

此篇文章重點將著重於實作 Flask Session Interface,資料庫採用活動之前介紹過的 SQLite 以及 Flask-Sqlalchemy 套件。

預備動作

本文將使用《Flask Web 開發實戰》第四次活動的程式碼來實作將 cookie 存入資料庫功能。請由下列指令從 github去得最新程式碼,並切換到 tag 8j

$ git clone https://github.com/win911/flask_class.git
$ git checkout 8j

所需的 package 列在 requirements.txt,使用下述指令安裝,前面括弧(venv)虛擬環境設定

(venv)$ pip install -r requirements.txt

本範例需要用到 Flask-Login 套件沒有寫在上述 requirements.txt,如果沒有請以下述指令安裝安裝。

(venv)$ pip install flask-login

如果是曾經做過之前活動程式碼,更新到此 tag 程式碼資料庫欄位有變動,或者是全新下載的程式碼 (資料庫尚未建立),都是以下列指令更新資料庫:

(venv)$ python manage.py db upgrade

關於SQLAlchemy 資料庫版本控制,參考《Flask Web 開發實戰》第三次活動 Database Migration 投影片

開發

要實作 Flask Session Interface,根據Flask Session Interface 文件,需要實作 open_session() 以及 close_session() 方法。除了自行實作這些方法,也可以使用 Flask-Session 套件。首先安裝套件:

(venv) $ pip install flask-session

要使用套件需要修改 config.py 加入 Flask-Session 設定,由於活動中使用 Flask-SQLAlchemy 套件,因此設定裡加上 SESSION_TYPE 設定。

SESSION_TYPE = 'sqlalchemy'

app/__init__.py 裡,加上 session 起始設定。

# 一開始 import 相關套件
from flask import Flask, session
from flask_session import Session
# 在 create_app(config_name) 方法裡加上下列兩行session = Session(app)
session.app.session_interface.db.create_all()

完整修改請見此 GitHub commit

完成上述修改後,開啟站台,網站登入和註冊等頁面會一切如常進行。

使用套件後的 Cookie 與 Session 的變化

Flask-Login 將 user id 等資訊儲存在 session 裡,再將 session 加密後儲存在 cookie 裡。如果 Session Protection 設為 strongsession 儲存的資訊還會再加上 IP addressuser-agent 等可以更明確定義 request 來源的資料,當發現新 request 裡的這些資料與 session 裡儲存的不一致或 session 過期時,cookie 就會被刪除,使用者就必須重新登入。

使用 Flask-Login,預設將 Session 資料加密存入 Cookie

Flask-Session 一樣將 user id 等資訊儲存在 session 裡,但改將 session 儲存在資料庫中,cookie 裡儲存的只是 session id (所以會發現 cookie 長度變短)。透過 session id,就可到資料庫中取得對應的 session 資料。

使用 Flask-Session 套件,cookie 長度變短
$ sqlite3 data-dev.sqlite

查看SQLite 資料庫裡面有哪些資料表,可以發現多了 sessions 資料表。

sqlite> .tables
alembic_version roles sessions users

查看 sessions table 資訊,其中包括 session_id,資料 data 則為 BLOB 型別:

sqlite> .schema sessions
CREATE TABLE sessions (
id INTEGER NOT NULL,
session_id VARCHAR(255),
data BLOB,
expiry DATETIME,
PRIMARY KEY (id),
UNIQUE (session_id)
);

利用 SQL command 可以取得 session id相對應 data

sqlite> SELECT quote(data) FROM sessions WHERE session_id='session:6b9750f1-21dd-4503-9a2b-f81e17863178';
X'80037D710028580A0000005F7065726D616E656E7471018858060000005F6672657368710289580A000000637372665F746F6B656E71035828000000666365393466643338326232353737343830633335643935333839313965386163346431366236327104752E'

Session id 帶有預設 prefixsession: ,可以透過 SESSION_KEY_PREFIX 參數設定。

Flask-Session 裡,session 資料透過 pickle 進行序列化後儲存在 sessions 資料表的 data 欄位。

如果想要修改 Session 資料表名稱,可透過 SESSION_SQLALCHEMY_TABLE 參數進行設定,其他可修改變數參考 Flask-Session 官方文件

小結

除了使用 Flask-Session 套件,也可以自行實作相關方法達成將此 session 存入資料庫的目的。在 Flask SnippetsSession 分類裡有其他使用者提供的數種 Flask Session Interface 方式可參考,下次電子報將繼續探索自行實作 Flask Session Interface的方法。

參考資料

--

--