什么是session?
session就是會話,客戶端和服務器直接的會話。他的粒度比http鏈接更粗,一次會話包含了多次連接。即一個session是多次http連接的集合。從我的客戶端連接到服務器到關閉客戶端,這期間的客戶端和服務器之間的聯系就是一次會話。
為什么需要session?
我們知道,http是無狀態的,每一次http連接之間是無關聯的。就好像加入a是客戶端,b是服務器,那么無狀態就是指a沒有記憶力,每一次a和b的對話(即每一次http連接),a都是記不住,a不記得自己之前是否跟b說過話,也不記得說話的內容,這就是http的無狀態。http的這個特性就導致了我們無法直接實現狀態登錄的保存,無法實現當登錄賬號后連接該服務器其他頁面時依舊保持着登陸的狀態。
所以為了解決問題,人們想出了很多方法,比如說登錄后在數據庫中對該用戶的數據打上登錄的標記,每次鏈接網頁就去查詢誰登錄了,但是這種辦法太笨,會造成對服務器的壓力。
還有一種辦法是利用cookie,cookie就是一種客戶端存儲技術。我們可以把用戶的信息存儲在cookie中,每次切換頁面就去cookie中查詢,保持該用戶的登錄狀態。但是這種辦法有一個巨大缺陷,就是不夠安全,信息是存儲在客戶端的,有可能被其他用戶惡意讀取篡改,所以這種辦法也不可行。
這時候人們就想,既然存儲在客戶端不安全,那我存在服務器不就相對安全了嗎?所以就有了session的誕生。所以總結下來,session就是一種在同一主機不同http請求之間保持狀態的技術手段
Session的機制
1.生成全局唯一標識符(sessionid);每個客戶端對應一個id,服務器識別客戶端后通過其id讀取session中的數據
2.開辟數據存儲空間。一般會在內存中創建相應的數據結構,但這種情況下,系統一旦掉電,所有的會話數據就會丟失,如果是電子商務網站,這種事故會造成嚴重的后果。不過也可以寫到文件里甚至存儲在數據庫中,這樣雖然會增加I/O開銷,但session可以實現某種程度的持久化,而且更有利於session的共享;
下面以Node.js中express框架的express-session插件來具體實現登錄狀態的保存(使用的MongoDB數據庫)
//當用戶點擊登錄選項時,以post方式將表單數據傳送到服務器
router.post('/login',function(req,res) {
//獲取表單數據 var body = req.body;
//User是數據庫模型 在該數據庫中查找是否有對應數據 User.findOne({ email:body.email, password:md5(md5(body.password)) },function(err,data) {
//服務器錯誤 if(err) { return res.status(500).json({ err_code:500, message:'server is busy' }); }
//如果找不到對應數據 說明輸入錯誤 if(!data) { return res.status(200).json({ err_code:1, message:'email or nickname is wrong!' }) }
//如果找到數據 則將找到的數據存入session的user屬性中 // 注意 存放的應該是數據庫中該用戶的數據 req.session.user = data; res.status(200).json({ err_code:0, message:'ok!' }) }) })
想要實現登錄狀態的保持,則存入的數據一定得是該用戶庫中存放的數據,方便后面的操作。存入數據后,無法用戶訪問該主機哪個頁面,數據都會存在,隨時都可以調用,也就實現了登錄狀態的保持
當我們想退出登錄時,則應該講解session數據清空,也就等於退出了登錄狀態
router.get('/logout',function(req,res) { req.session.user = null; res.redirect('/'); })