什么是Session?簡單講,Session是一種服務端用於保存每個客戶端用戶的狀態信息的機制。客戶端第一次訪問時,服務端從分配一個空間專門存儲該客戶端的信息,后續訪問時便可以直接獲取或者更新狀態信息。具體關於Session定義請查看參考。
.NET下Session使用很簡單,對寫入Session值無類型限制,設置Session有效時間也很簡單,直接設置Session的timeout屬性即可,類型為int,單位為分鍾。
1 Session["time"] = DateTime.Now.ToString("yyyymmddHHMMss"); 2 Session.Timeout = 60;
但若要設置多個有效時間不同的Session,就不那么友好了,后設置的有效時間會覆蓋之前值。
1 //寫入用戶登錄狀態到Session。
2 Session["state"] = "On"; 3 //設置用戶登錄狀態有效時間為1天,除非登錄清空Session,否則整天登錄狀態有效。
4 Session.Timeout = 60 * 24; 5
6 //設置類似驗證碼類似的session,假設有效時間為1分鍾。
7 Session["time"] = DateTime.Now.ToString("yyyymmddHHMMss"); 8 Session.Timeout = 1;
原因在於C#中只提供了session有效時間統一設置方法,無法對單個session進行有效時間進行設置。
因此要在服務端對多個session分別設置有效時間就只能另辟蹊徑,可以采用的方法大致分為兩類:
- 基於session機制進行擴展,通過擴展方法實現,即方案1和方案3。目前並沒有從博客園或者相關文獻中找到方案,唯一找到的參考資料方案3中有提及。
- 考慮使用redis等替代session功能,redis允許對特定鍵值對設置有效時間,方案2。該類型的方案較多,博客園各位大大都有文獻介紹,所以本文重點不在這里。
方案1:構建結構為: Tuple.Create<string, object, int>(key, value, time) 的tuple元組,將tuple寫入Session中。
寫入時根據傳入有效時間計算出過期時間,將過期時間存入,獲取Session時判斷是否已經超過過期截止時間,超過返回空,並且清空Session。
1 private void SetSingleSession(string key, object value, int? timeout) 2 { 3 int time = timeout ?? Session.Timeout; 4 DateTime endTime = DateTime.Now + new TimeSpan(0,time,0); 5 var tuple = Tuple.Create(key, value, endTime); 6 Session[key] = tuple; 7 }
1 private object GetSingleSession(string key) 2 { 3 var tuple = Session[key] as Tuple<string, object, DateTime>; 4 var diff = DateTime.Compare(tuple.Item3, DateTime.Now); 5 object result = null; 6 if (diff > 0) result = tuple.Item2;//有效時間截止之前正常返回值 7 else Session.Remove(key);//超過有效時間清空Session 8 return result; 9 }
方案2:使用Redis。
- 安裝redis服務。windows版:https://github.com/MSOpenTech/redis/release,下載安裝包並點擊安裝,直到安裝完成。
-
設置登錄密碼,打開cmd窗口,輸入“cd C:\Program Files\redis”進入redis安裝目錄,輸入“redis-cli.exe”運行該exe程序,繼續輸入 “config pass requirepass password”(password改為要設置的登錄密碼),完成密碼設置。
- Nuget中安裝“StackExchange.Redis”.
- redis使用,基礎代碼如下。
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379,password=fxy123"); IDatabase db = redis.GetDatabase(); //寫入記錄,包括有效時間:10秒過期
db.StringSet ( "key_test" , "shaocan",TimeSpan.FromSeconds(10));
方案3:通過擴展Session類,設置一個異步延遲執行機制,定時清除session。(原始文獻參考ASP.NET Session: Caching Expiring Values)
public static class SessionHelper { public static void AddWithTimeout(this HttpSessionStateBase session,string name,object value,int? minute) {
TimeSpan timeSpan=TimeSpan.FromMinutes(minute??session.TimeOut);
lock (session) { session[name] = value; } Task.Delay(expireAfter).ContinueWith((task) => { lock (session) { session.Remove(name); } }); } }
如果不是特別龐大的項目,推薦使用方案三,簡單擴展方法即可實現,只需設置時使用Session擴展方法即可;對於比較大的項目,推薦使用方案2進行管理,畢竟Session機制由於服務器重啟等原因會丟失,造成用戶體驗不佳。不推薦使用方案1,如果使用方案1設置和獲取session都必須采用該擴展類進行,否則會存在過期但並未失效的情況。
如果您覺得本文有參考價值或者不足之處,請留下您的建議。謝謝。