WARNING!
閱讀本文需要具有使用python編程的能力以及Web編程的經驗,起碼應該知道python是什麼,Session是什麼。初學者慎入,某些描述語焉不詳,小心誤入歧途,歡迎高手踴躍拍磚。本文代碼僅僅作為樣本使用,用於說明在tornado中實現session的過程以及方法,未經過任何編譯或者運行,請勿直接copy到項目中使用,本人不對此行為造成的後果負任何責任。(此文實現內容來源於商業項目,恕未能直接提供源碼)
----------------------------------------------------------
tornado沒有提供預設的會話,而很多敏感資訊又沒法用cookie存,tornado提供的secure_cookie只是解決了防止cookie篡改而沒法阻止資料被解密為明文,所以我就給tornado寫了一個session的包來解決這個問題。嗯,我們來看看是如何從底層一磚一瓦的來實現Session的功能。
根據項目的需要我採用Memcached作為Session的backend,當然你願意用Mysql或者是其他什麼能儲存資料的東西都行,比如文字檔或者mongodb,選擇很多,所以我們將Session需要持久化的操作獨立出來成為一個可以替換的backend模組,我們可以根據配置使用不同的backend,由於python得ducktyping特性,要實現起來相當的簡單,我們只需要提供包含如下三個方法簽名的類就行了
class backend():
def getitem(self,key):
def setitem(self,key,value,timeout)
def deleteitem(self,key)
對於Memcached我們需要在backend類中保持一個Memcached的串連,大體上的實現如下:
from memcache import Client
class backend():
def __init__(self):
self.conn=Client([‘127.0.0.1:11211’])
def getitem(self,key):
return self.conn.get(key)
def setitem(self,key,value,timeout):
self.conn.set(key,value,timeout)
def deleteitem(self,key):
self.conn.delete(key)
當然實際應用中我們不會寫得這麼簡陋了,已連線的服務器資訊都是從設定檔裡取得的。這樣我們就有了一個Session的backend了,如果你想用Mysql作為backend,那麼可以按照這個原理來改寫一個backend類
有了Session資料的持久化backend後我們就可以開始編寫Session類本身了,首先我們來回顧一下Session的工作原理。基本上大部分的Session都是通過Cookie佈建服務端持久化來實現Session的,cookie保持使用者建立會話的SessionID,然後在每次訪問的時候通過SessionID到持久化服務中去取這個Session的資料。當一個request開始的時候過程如:
當一個request結束之後,過程如:
理清楚處理的邏輯我們就能開始編碼了,首先我們需要用一個對象來儲存Session的資料,一般來說Session都按照Key-Value的形式儲存,所以我們可以用一個Dict來作為Session的儲存物件,但是我們還需要一個Session ID,所以我們繼承一個dict
class SessionData(dict):
def __inti__(self,id=none):
self.id=id
def __getitem__(self,key):
if self.has_key(key):
return self[key]
return None
def __setitem__(self,key,value):
self[key]=value
然後我們實現一個decorator來在一個request前和request後來恢複和儲存Session
def Session(request):
def Process(handler,*args):
#請求前恢複Session對象的過程
item=handler.application.backend.getitem(handler.get_secure_cookie(‘session_id’,’’))
data=None
if item:
data=new SessionData(item.id)
data.update(item)
else:
data=new SessionData()
handler.set_secure_cookie(“session_id”,””)
handler.setattr(“session”,data)
request(handler,*args)#執行原本請求的方法
#請求完成後儲存session的過程
if data.id:
handler.application.backend.setitem(data.id,data)
else:
if len(data.keys()):
data.id=str(uuid1.uuid1())
handler.set_secure_cookie(“session_id”,data.id)
handler.application.backend.setitem(data.id,data)
這個方法有點長,不過邏輯就是這麼樣子的,實現了這個decreator之後我們只需要在需要使用Session的請求前加上@Session,就能夠通過self.session來使用session咯。
接下來想在項目裡使用還有一些具體的問題要解決,但是基本原理和實現方式在本文的內容就到此為止了,接下來的工作應該難不倒能看懂此文的同學,如果看著如同天書,那麼多半是對python或者tornado沒有什麼瞭解,請自行彌補基礎知識。希望此文能夠對正在實踐python和tornado的TX有所幫組