webpy使用系列之session的使用,雖然工作中使用的是django,但是自己并不喜歡那種大而全的東西~什么都給你準(zhǔn)備好了,自己好像一個(gè)機(jī)器人一樣趕著重復(fù)的基本工作,從在學(xué)校時(shí)候就養(yǎng)成了追究原理的習(xí)慣,從而有了這篇session的使用和說明。
PS:其實(shí)有些總結(jié)的東西挺好的,想分享給大家看,而不是枯燥的代碼,這東西說實(shí)話對(duì)其他人用處不大,但都被移除首頁(yè)了~~
下面為官方的例子,用session來存儲(chǔ)頁(yè)面訪問的次數(shù),從而實(shí)現(xiàn)對(duì)訪問次數(shù)的記錄。
?。≒S,這里記錄是針對(duì)一個(gè)客戶端來說的訪問次數(shù),而不是官方文檔說的統(tǒng)計(jì)有多少人正在使用session,因?yàn)槊總€(gè)客戶端的session并不相同,服務(wù)器會(huì)根據(jù)不同的sessionid來區(qū)分不同的客戶端的session)
需要注意的是,官方說明在調(diào)試情況下,session并不能正常的運(yùn)行,所以需要在非調(diào)試摸下測(cè)試,那么就有了下面的這個(gè)例子。
import web
#非調(diào)試模式web.config.debug = Falseurls = ( "/count", "count", "/reset", "reset")app = web.application(urls, locals())session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'count': 0})class count: def GET(self): session.count += 1 return str(session.count)class reset: def GET(self): session.kill() return ""if __name__ == "__main__": app.run()
在官方文檔中,對(duì)上述debug模式的現(xiàn)象給出了這樣的解釋:
session與調(diào)試模試下的重調(diào)用相沖突(有點(diǎn)類似firefox下著名的Firebug插件,使用Firebug插件分析網(wǎng)頁(yè)時(shí),會(huì)在火狐瀏覽器之外單獨(dú)對(duì)該網(wǎng)頁(yè)發(fā)起請(qǐng)求,所以相當(dāng)于同時(shí)訪問該網(wǎng)頁(yè)兩次)
為了解決上述問題,官方給出了進(jìn)一步的解決方法,如下
import weburls = ("/", "hello")app = web.application(urls, globals())if web.config.get('_session') is None: session = web.session.Session(app, web.session.DiskStore('sessions'), {'count': 0}) web.config._session = sessionelse: session = web.config._sessionclass hello: def GET(self): print 'session', session session.count += 1 return 'Hello, %s!' % session.countif __name__ == "__main__": app.run()
由于web.session.Session會(huì)重載兩次,但是在上面的_session并不會(huì)重載兩次,因?yàn)樯厦娑嗔艘粋€(gè)判斷_session是否存在于web.config中。
其實(shí),在web.py文件中,定義了config,而Storage在下面的圖中并沒有特殊的結(jié)果,像字典一樣~
#web.pyconfig = storage()#utils.pystorage = Storage
雖然官方文檔中提到,只能在主程序中使用session,但是通過添加__init__.py可以條用到該頁(yè)面的session,也就是說一樣使用session。
官方給出的方法更加合理化一點(diǎn),通過應(yīng)用處理器,加載鉤子(loadhooks)
在webpy中,應(yīng)用處理器為app.add_processor(my_processor),下面的代碼添加到上述的完整例子中,可以再處理請(qǐng)求前和處理請(qǐng)求后分別條用my_loadhook()和my_unloadhook()。
def my_loadhook(): print "my load hook"def my_unloadhook(): print "my unload hook"app.add_processor(web.loadhook(my_loadhook))app.add_processor(web.unloadhook(my_unloadhook))
結(jié)果如下,我在處理中打印了session:
從而,可以再web.loadhook()中加載session信息,在處理之前從web.ctx.session中獲取session了,甚至可以在應(yīng)用處理器中添加認(rèn)證等操作。
#main.pydef session_hook(): web.ctx.session = sessionapp.add_processor(web.loadhook(session_hook))#views.pyclass edit: def GET(self): try: session = web.ctx.session username = session.username if not username: return web.redirect('/login') except Exception as e: return web.redirect('/login') return render_template('edit.html')
對(duì)于服務(wù)器來說,怎樣才能區(qū)分不同客戶端呢,怎樣才能區(qū)分不同客戶端的session呢?
是通過sessionid來實(shí)現(xiàn)的,最初我還傻傻的分不清session和cookie,以及不同用戶之間的信息室如何分配的!
如上圖,是生成sessionid的代碼段,其中包含了隨機(jī)數(shù)、時(shí)間、ip以及秘鑰。
在客戶端訪問服務(wù)器時(shí),服務(wù)器會(huì)根據(jù)上述信息來計(jì)算一個(gè)針對(duì)客戶端唯一的sessionid,并通過cookie保存在客戶端中。
客戶端用cookie保存了sessionID,當(dāng)我們請(qǐng)求服務(wù)器的時(shí)候,會(huì)把這個(gè)sessionID一起發(fā)給服務(wù)器,服務(wù)器會(huì)到內(nèi)存中搜索對(duì)應(yīng)的sessionID,如果找到了對(duì)應(yīng)的 sessionID,說明我們處于登錄狀態(tài),有相應(yīng)的權(quán)限;如果沒有找到對(duì)應(yīng)的sessionID,這說明:要么是我們把瀏覽器關(guān)掉了(后面會(huì)說明為什 么),要么session超時(shí)了(沒有請(qǐng)求服務(wù)器超過20分鐘),session被服務(wù)器清除了,則服務(wù)器會(huì)給你分配一個(gè)新的sessionID。你得重新登錄并把這個(gè)新的sessionID保存在cookie中。
session的結(jié)構(gòu)
上面提到了session在webpy中式一種dict的方式存儲(chǔ),
在webpy的session中,存儲(chǔ)方式包括兩種DiskStore和DBStore,分別為硬盤存儲(chǔ)和數(shù)據(jù)庫(kù)存儲(chǔ)。
而session的存儲(chǔ)也可以看出來,把sessionid作為key來存儲(chǔ)session信息
http://doc.outofmemory.cn/python/webpy-cookbook/
http://webpy.org/docs/0.3/tutorial
聯(lián)系客服