.NET實現多個不同有效時間Session方案思考


  什么是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都必須采用該擴展類進行,否則會存在過期但並未失效的情況。

  如果您覺得本文有參考價值或者不足之處,請留下您的建議。謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM