摘要:基于以上原因,很多管理都是基于實現(xiàn)的。在經(jīng)過中間件的時候就會自動完成的有效性驗證延期重新頒發(fā)以及對中數(shù)據(jù)的獲取了。上述代碼只是對于請求的靜態(tài)處理,整個用戶管理的另一個方面則是狀態(tài)的切換用戶的登陸登出以及用戶數(shù)據(jù)的獲取。
基礎(chǔ)概念
Session管理是Web Application的基礎(chǔ)也是一個老生常談的話題。為了方便后文的展開,更重要的是確認(rèn)自己清晰的理解了整個Session管理的概念,我在此還是決定贅述的整個流程。如果你已經(jīng)對于Session概念非常清晰的話,可以跳過本節(jié)不影響對于后文的理解。
HTTP協(xié)議在設(shè)計的時候是無狀態(tài)的。這是一個很關(guān)鍵的概念,意味著服務(wù)器在處理請求的時候,并不關(guān)注這個請求是誰發(fā)來的。這對于以提供內(nèi)容為核心的Web1.0,例如門戶網(wǎng)站,非常適合。然而對于以應(yīng)用服務(wù)為核心的Web 2.0而言,服務(wù)器端必須有能力從請求中提取出請求者的身份信息,以在請求者不用反復(fù)輸入身份的情況下,提供連續(xù)的服務(wù)。
實現(xiàn)請求身份驗證的方式很多,其中一種廣泛接受的方式是使用服務(wù)器端產(chǎn)生的Session ID結(jié)合瀏覽器的Cookie實現(xiàn)對Session的管理,一般來說包括以下4個步驟:
服務(wù)器端的產(chǎn)生Session ID
服務(wù)器端和客戶端存儲Session ID
從HTTP Header中提取Session ID
根據(jù)Session ID從服務(wù)器端的Hash中獲取請求者身份信息
上圖是一個使用Redis Cluster來實現(xiàn)對Session管理的流程,但本質(zhì)上除了redisMatrix.get和redisMatrix.set以外,和一般的Session管理流程是一致的。
簡單來說,一個請求到達(dá)的時候,服務(wù)器會先判斷是否帶有Session信息。如果有,則根據(jù)Session ID去數(shù)據(jù)庫中查找是否具有對應(yīng)的用戶身份信息。此處可能會出現(xiàn)Session失效、非法的Session信息等可能性,那么服務(wù)器視同無Ssession信息的情況,重新的產(chǎn)生一個隨機(jī)的字符串,并且在Http返回頭中寫入新的Session ID信息。另一者,如果服務(wù)器成功獲取了用戶的身份信息則以該身份為請求者提供服務(wù)。
使用Express和Redis對Session管理的實現(xiàn)Redis是一個非常適合用于Session管理的數(shù)據(jù)庫。第一,它的結(jié)構(gòu)簡單,key-value的形式非常符合SessionID-UserID的存儲;第二,讀寫速度非常快;第三,自身支持?jǐn)?shù)據(jù)自動過期和清除;第四,語法、部署非常簡單?;谝陨显?,很多Session管理都是基于Redis實現(xiàn)的。
Express已經(jīng)將Session管理的整個實現(xiàn)過程簡化到僅僅幾行代碼的配置的地步了,你完全不用理解整個session產(chǎn)生、存儲、返回、過期、再頒發(fā)的結(jié)構(gòu),使用Express和Redis實現(xiàn)Session管理,只要兩個中間件就足夠了:
express-session
connect-redis
廢話不多說還是上代碼:
var express = require("express"); var session = require("express-session"); var RedisStore = require("connect-redis")(session); var app = express(); var options = { "host": "127.0.0.1", "port": "6379", "ttl": 60 * 60 * 24 * 30, //Session的有效期為30天 }; // 此時req對象還沒有session這個屬性 app.use(session({ store: new RedisStore(options), secret: "express is powerful" })); // 經(jīng)過中間件處理后,可以通過req.session訪問session object。比如如果你在session中保存了session.userId就可以根據(jù)userId查找用戶的信息了。
req在經(jīng)過session中間件的時候就會自動完成session的有效性驗證、延期/重新頒發(fā)、以及對session中數(shù)據(jù)的獲取了。
上述代碼只是對于請求的Session靜態(tài)處理,整個用戶管理的另一個方面則是狀態(tài)的切換(用戶的登陸、登出)以及用戶數(shù)據(jù)的獲取。
exports.signin = function(params, req, res){ var username = params.username; var password = params.password; //查找用戶信息,看是否滿足登陸條件 var user = findUser(username, password); if(user){ //成功獲取用戶對象 req.session.regenerate(function(){ req.user = user; req.session.userId = user.id; req.session.save(); //保存一下修改后的Session res.redirect("/account"); }); } else{ //用戶信息不符合,登陸失敗 } } exports.signout = function(req, res){ req.clearCookie("connect.sid"); req.user = null; req.session.regenerate(function(){ //重新生成session之后后續(xù)的處理 res.redirect("/signin"); }) } exports.persist = function(req, res, next){ var userId = req.session.userId; //通過user id去數(shù)據(jù)庫里面查找User對象 var user = findUserById(userId); if(user){ req.user = user; next(); } else{ //該用戶不存在 } }Session的安全問題
SessionId就如同請求者的身份證,一旦被攻擊者惡意獲得,攻擊者便可以偽裝成請求者對服務(wù)器發(fā)起請求,也就是我們經(jīng)常聽到的會話劫持(Session/Cookie Hijack)
關(guān)于會話劫持的原理推薦大家去看這篇文章
基于上述實現(xiàn)方法的Session管理,我認(rèn)為基本上可以排除
暴力破解SessionId
惡意植入固定SessionId
兩種可能,因為uid的庫基本上可以保證SessionId的隨機(jī)性;而傳遞SessionId則依賴HTTP請求頭中的Cookie信息而非URL,同時在用戶登錄立刻更換SessionId。
唯一的可能性來源于Session的監(jiān)聽,而對于這種攻擊有效的兩種防止辦法是:
Https
很多網(wǎng)站僅僅在Login的階段使用Https防止用戶的用戶名、密碼信息被監(jiān)聽者獲取,但是隨后的SessionId同樣有可能被監(jiān)聽者獲取而偽造登錄者的身份信息。因此更加推薦的方式是所有的信息傳遞全部使用Https實現(xiàn),這樣即使監(jiān)聽著截獲了信息也無法破解其中的內(nèi)容。關(guān)于如何使用NodeJS建立一個HTTPS的server可以參考《HTTPS的原理和NodeJS的實現(xiàn)》 這篇文章
httpOnly
Express在options中提供了httpOnly的屬性,此屬性默認(rèn)值為true,這個屬性保證了Cookie的信息不能夠通過JavaScript腳本獲取。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/85588.html
世界上任何一個擁有用戶數(shù)據(jù)的 web 應(yīng)用都必須處理 sessions。作為一名開發(fā)者,我們必須要知道它們是什么以及如何處理它們。在這篇文章中,我想要分享的是: session 是什么? session 如何存儲數(shù)據(jù)? 你如何決定存放 session 數(shù)據(jù)的位置? 在 sessions 工作時,你必須意識到的安全性上的影響有哪些?在一些示例代碼中,我將會運用?session npm modul...
摘要:當(dāng)會話過期或被放棄后,服務(wù)器將終止該會話。原來中間件生成的是一個對象,里面包含了信息。這個有一個過期時間,比如,上面代碼中設(shè)置的是小時。也就是說,小時后,這個在瀏覽器中會自動消失。 前言 在上一篇中node中的cookie,對cookie進(jìn)行了相關(guān)介紹,本篇將繼續(xù)前行,對session進(jìn)行說明。 session是什么 session不就是會話嘛,那什么是會話呢?會話是一個比連接粒度更大...
摘要:當(dāng)會話過期或被放棄后,服務(wù)器將終止該會話。原來中間件生成的是一個對象,里面包含了信息。這個有一個過期時間,比如,上面代碼中設(shè)置的是小時。也就是說,小時后,這個在瀏覽器中會自動消失。 前言 在上一篇中node中的cookie,對cookie進(jìn)行了相關(guān)介紹,本篇將繼續(xù)前行,對session進(jìn)行說明。 session是什么 session不就是會話嘛,那什么是會話呢?會話是一個比連接粒度更大...
閱讀 3777·2021-11-11 11:02
閱讀 3507·2021-10-11 10:57
閱讀 3620·2021-09-22 16:00
閱讀 1856·2021-09-02 15:15
閱讀 1342·2019-08-30 15:56
閱讀 1018·2019-08-30 15:54
閱讀 2746·2019-08-30 12:43
閱讀 3551·2019-08-29 16:06