2017-04-12 20 views
0

我有一個使用快速框架的nodejs web應用程序,它可以通過互聯網到達。 我正在使用將會話存儲爲磁盤上的純文件的會話存儲,並且對於當前實現,每個沒有cookie的請求都將獲得新的會話ID,從而導致新會話磁盤上的新文件。如何防止node.js應用程序中的會話溢出?

由於應用程序是通過互聯網訪問,我收到很多無效的請求,這當然從來沒有在我的文件系統,這是一個真正的混亂髮送cookie,但產生更多的會話。

我使用OWASP會話管理備忘單作爲實施指南(https://www.owasp.org/index.php/Session_Management_Cheat_Sheet),但未包括訪客會話的詳細主題。它只說明應用程序可能會發現將會話也分配給未經身份驗證的(來賓)用戶很有用,因此訪客會話似乎總體上是有效的功能。

所以現在我不知道如何正確地解決無效/惡意請求造成的不必要的會話/會話文件問題。有沒有推薦的方法來做到這一點?
我想也許是一個非常短的'客人'會話到期(< 5分鐘)和IP範圍的白名單或某事的組合,其中任何IP不在白名單中都不會收到訪客會話(當然,但當然會話一旦成功認證)。

關於我該如何解決這個問題的任何提示?

+0

爲什麼你認爲在純文件中創建和存儲會話是安全的方式?會話最好存儲在標有過期日期的內存/緩存服務器中。此外,如果您收到很多無效請求,請嘗試限制IP或者甚至禁止某些IP。無論哪種方式,我相信你正在推翻它,並增加許多預防措施,使你的應用程序無法維護。嘗試使用像頭盔這樣的模塊並閱讀有關確保快速應用的文章 – Gntem

回答

1

不管你如何存儲你的會話,你將面臨同樣的問題。在某個時候,你的會話存儲將會溢出(磁盤空間不足,內存耗盡,inode等耗盡)。

你需要做的是修剪你的會話。除非您真的可以負擔無限期地存儲會話,否則應該在會話cookie上設置到期日期。對於客戶端瀏覽器將負責刪除cookie。對於服務器,您需要定期檢查所有會話以查看是否有任何已過期。

接下來你做什麼很簡單。無論您選擇存儲會話的技術如何,您都可以簡單地刪除過期的會話。這可以在您的節點進程內(在某些setTimeout()處理程序內)或在您的節點進程外(可能是簡單的每日cron作業)完成。

在刪除陳舊的會話文件之前,您應該允許一些寬限期(1分鐘,1小時,1天等),以防止刪除會話文件和加載網站的用戶之間的競爭狀態。

您可能還希望允許用戶在每次訪問時刷新會話過期日期。對於基於文件的會話存儲,這可以像觸摸文件以更新上次修改時間一樣簡單。

有一種情況是這種策略不起作用。由於性能原因(例如,InnoDB,MySQL)刪除數據時,某些數據庫不會釋放磁盤空間。相反,數據只是標記爲已刪除,但數據庫不斷增長。在這種情況下,你唯一的出路就是改變會話存儲。但是由於您使用的是文件存儲,因此您不必擔心這個問題。

+0

你在這裏得到了一些好點。根據OWASP的要求(空閒超時,絕對超時,自動更新),我已經有會話超時和循環檢查。它將根據這些超時刪除會話。但是應用程序需求包括經過身份驗證的用戶會話的相當長的使用期限,因此,訪客會話當前也受到影響。 也許我應該引入訪客會話的單獨(短暫)超時,並且不要將訪客會話存儲爲持久性。 – user826955

+0

@ user826955:是的,就是這樣做的。一旦您的網站變得流行,通常沒有登錄的用戶將遠遠超過登錄用戶。特別是一旦你的網站被谷歌索引。如果你使用谷歌,它會被其他爬蟲抓取。至少會有必應,雅虎和百度 – slebetman

1

爲您的使用情況是Redis的,Memcached的或其他一些快速內存數據存儲,但請注意,所有的會話數據將不得不適應RAM的最佳會話存儲。

另一種選擇是使用基於磁盤的數據庫,如任何RDBMS或Mongo,Couch,Rethink等,但要確保速度很快,否則你的性能將大大降低。

與最高的可擴展特性,最快的方式是不要任何會話數據存儲在服務器上,而是依賴於餅乾或其他客戶端存儲,例如發送的數據使用JWT - 請參閱:https://jwt.io/ - 但請注意,通過這種方式,您將無法控制一次發佈的會話令牌,除非您引入數據庫來檢查它們是否有效以及使其無效的機制,但此時您具有相同的就像在服務器上存儲數據一樣,可能存在的問題是可能存儲的數據可能更少,並且不需要經常更新。

這裏的每一個方法都有優點和缺點,但存儲在文件系統中的文件數據是從來沒有生產的最佳解決方案的任何數據,不僅爲會話數據。如果你的用例中的缺點是可以接受的,你應該使用一個數據庫或者在客戶端存儲數據。

+0

正如你已經提到的那樣,正如@slebetman所提到的,存儲技術是無關緊要的,因爲任何可能的技術都會在某些時候溢出。 我想堅持服務器端會話存儲,因爲這是(至少對於我的理解/研究/知識)更安全,也是OWASP推薦的。 – user826955

0

這是要避免的事情:

app.use(session({ ... })); 
app.use(express.static(...)); 

這將創造所有靜態請求會話。

您可以減輕通過禁用saveUninitialized setting

app.use(session({ 
    saveUninitialized : false, 
    ... 
})); 
app.use(express.static(...)); 

這將阻止新的,但是非修飾會話存儲。由於靜態資源不會修改會話,因此不會爲其創建會話。

另一種選擇是,以使會議的只有你的路由的子集:

const session = require('express-session'); 

let sessionMiddleware = session({ ... }); 

app.use('/api', sessionMiddleware, apiRouter); 
+0

雖然我正在使用會話管理的自定義實現(並沒有按照公司的要求提供表達式中間件),但我喜歡不會將訪客會話刷新到存儲的想法,而只是將其保存在內存中。大概這可以與@slebetman提到的想法一起解決。 – user826955

+0

@ user826955不保存在請求生命週期內未被修改的新會話的想法可能會幫助您節省大量文件I/O。 – robertklep