【原始碼剖析】tornado-memcached-sessions —— Tornado session 支援的實現(三)
阿新 • • 發佈:2018-11-01
新地址:https://github.com/AngryHacker/articles/issues/5#issue-372211594
童鞋,我就知道你是個好學滴好孩子~來吧,讓我們進行最後的探(zuo)索(si)!
上一次我們講到哪裡?哦。。。準備講 SessionManager 是吧,來~一個一個函式看~
首先是初始化,設定金鑰, memcache 地址,session 超時時間。
# 初始化需要一個用於 session 加密的 secret, memcache 地址, session 的過期時間 def __init__(self, secret, memcached_address, session_timeout): self.secret = secret self.memcached_address = memcached_address self.session_timeout = session_timeout
接著是 _fetch 方法,以 session_id 為鍵從 memcached 中取出資料,並用 pickle 反序列化解析資料:
# 該方法用 session_id 從 memcache 中取出資料 def _fetch(self, session_id): try: # 連線 memcache 伺服器 mc = memcache.Client(self.memcached_address, debug=0) # 獲取資料 session_data = raw_data = mc.get(session_id) if raw_data != None: # 為了重新重新整理 timeout mc.replace(session_id, raw_data, self.session_timeout, 0) # 反序列化 session_data = pickle.loads(raw_data) # 如果拿到的資料是字典形式,才進行返回 if type(session_data) == type({}): return session_data else: return {} except IOError: return {}
get 經過安全檢查後,以 SessionData 的形式返回 memcached 的資料(呼叫了 _fetch)方法。
def get(self, request_handler = None): # 獲取對應的 session_id 和 hmac_key if (request_handler == None): session_id = None hmac_key = None else: # session 的基礎還是靠 cookie session_id = request_handler.get_secure_cookie("session_id") hmac_key = request_handler.get_secure_cookie("verification") # session_id 不存在的時候則生成一個新的 session_id 和 hmac_key if session_id == None: session_exists = False session_id = self._generate_id() hmac_key = self._generate_hmac(session_id) else: session_exists = True # 檢查 hmac_key check_hmac = self._generate_hmac(session_id) # 不通過則丟擲異常 if hmac_key != check_hmac: raise InvalidSessionException() # 新建 SessionData 物件 session = SessionData(session_id, hmac_key) if session_exists: # 通過 _fetch 方法獲取 memcache 中該 session 的所有資料 session_data = self._fetch(session_id) for key, data in session_data.iteritems(): session[key] = data return session
至於 set 方法,是為了更新 memcached 的資料。
# 設定新的 session,需要設定 handler 的 cookie 和 memcache 客戶端
def set(self, request_handler, session):
# 設定瀏覽器的 cookie
request_handler.set_secure_cookie("session_id", session.session_id)
request_handler.set_secure_cookie("verification", session.hmac_key)
# 用 pickle 進行序列化
session_data = pickle.dumps(dict(session.items()), pickle.HIGHEST_PROTOCOL)
# 連線 memcache 伺服器
mc = memcache.Client(self.memcached_address, debug=0)
# 寫入 memcache
mc.set(session.session_id, session_data, self.session_timeout, 0)
最後的兩個函式,一個是生成 session_id,另一個用 session_id 與金鑰加密後生成一個加密字串,用於驗證。
# 生成 session_id
def _generate_id(self):
new_id = hashlib.sha256(self.secret + str(uuid.uuid4()))
return new_id.hexdigest()
# 生成 hmac_key
def _generate_hmac(self, session_id):
return hmac.new(session_id, self.secret, hashlib.sha256).hexdigest()
我們在哪裡初始化了 SessionManager 呢?還記得第一篇裡面的 Application 類嗎?噢...快回去翻翻。
好了,童鞋們我們放學了,大家回家吧~對本篇部落格有任何意見,拒絕吐槽!