這兩天端午節。趁着端午節沒事干,寫了個flask的擴展——flask-RedisSession
在flask中使用該擴展可以讓你借助redis數據庫輕松獲得server-side session.
這個flask擴展可以使用pip install flask-redissession
獲得,也可以進入flask-redissession給我個star 給我提問題/建議...
由於寫這個擴展包的需要,我重新研究了一下flask中session的部分。以下部分是我擴展包中的過程。
open_session
當用戶發送請求的時候,request被傳到服務器。由於使用的是server-side session,這個request中就包含一個sessionID。后台程序調用open_session
方法,來解析這個request,獲得session。具體的過程如下:
-
后台程序解析request,通過
session_cookie_name
獲得sessionID
(如果沒有,就設置為None
) -
檢驗這個
sessionID
是否存在。如果不存在,則生成一個sessionID,然后創建一個session,並返回給客戶端 -
sessionID
存在。檢驗是否使用SECRET_KEY
來簽名。如果使用,則調用Signer
函數生成Signer對象,並對這個sessionID進行unsigner
操作。signer = Signer(app.secret_key, salt='flask-redis-session', key_derivation='hmac') sessionid = signer.unsign(sessionid).decode('utf-8')
-
根據unsigner操作獲得的結果在redis數據庫中查找對應的session(已序列化),並對session反序列化。如果根據sessionID沒找到,則創建一個新的session並返回給客戶端
-
把查找到的session返回給客戶端
save_session
如果session發生改變,就會調用這個方法(先刪除原session,再set_session
)。
在save_session中,我們需要知道:
-
把session被序列化后的東西存入redis數據庫:
以下是序列化的代碼serialize_session = self.serialization_method.dumps(dict(session))
-
需要在每次session發生改變的時候重置過期時間。
-
如果使用
SECRET_KEY
進行簽名,則在給用戶返回sessionID之前,需要對原sessionID進行簽名:session_id = Signer(app.secret_key, salt='flask-redis-session', key_derivation='hmac').sign(session.session_id.encode('utf-8')) #對session_id進行解碼,轉為str session_id = session_id.decode('utf-8')
-
調用
set_session
為用戶設置新的session。其中傳輸的值為簽名后的sessionID
總結
- redis數據庫使用字符串對象存儲session。
鍵:未簽名的sessionID
值:序列化的session - 用戶請求中(request)的sessionID是已簽名sessionID,在服務器中需要unsign操作才能獲得真正的sessionID
- 當session發生改變的時候,服務器需要在redis中刪除原session,並調用
delete_cookie
讓客戶端刪除這個session;然后向redis中寫入新的session(需要序列化),並通過調用set_session
把簽名后的sessionID回傳給客戶端