首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 實現單用戶單點登錄:防止同一賬號重複在線

     編輯:ASP.NET 基礎

基於 Cache/Application 的併發登錄控制方案

業務常見需求:同一賬號同一時間僅允許一個會話在線,新登錄擠掉舊會話或拒絕新登錄。本文提供兩種實現思路,均利用服務端全局狀態存儲。

方案一:Cache + Session 聯動 (推薦)

// 登錄頁邏輯
string sKey = username.Text.Trim();
string cachedUser = Cache[sKey]?.ToString();

if (string.IsNullOrEmpty(cachedUser))
{
    // 首次登錄:寫入 Cache,過期時間同步 Session Timeout
    TimeSpan timeout = TimeSpan.FromMinutes(Session.Timeout);
    Cache.Insert(sKey, sKey, null, DateTime.MaxValue, timeout, 
                 CacheItemPriority.NotRemovable, null);
    Session["User"] = sKey; // 正常登錄流程
}
else if (cachedUser == sKey)
{
    // 已在線:提示並阻止
    ClientScript.RegisterStartupScript(GetType(), "alert", 
        "alert('該賬號已在其他地方登錄');", true);
    return;
}
else
{
    // 異常狀態:清理 Session 重試
    Session.Abandon();
}

關鍵:客戶端關閉瀏覽器時清理 Cache


// 頁面 onUnload 事件 (需考慮瀏覽器兼容性)
window.onunload = function() {
    $.ajax({
        type: "POST",
        url: "ClearCache.aspx",
        data: { sKey: "<%= sKey %>" },
        async: false // 同步請求確保發送完成
    });
};

// ClearCache.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
    string key = Request.Form["sKey"];
    if (!string.IsNullOrEmpty(key)) Cache.Remove(key);
}

// Global.asax Session_End 兜底清理
void Session_End(object sender, EventArgs e)
{
    Hashtable online = (Hashtable)Application["Online"];
    if (online?[Session.SessionID] != null)
    {
        online.Remove(Session.SessionID);
        Application.Lock();
        Application["Online"] = online;
        Application.UnLock();
    }
}

方案二:Application Hashtable 記錄在線映射


// 登錄檢查
public bool CheckOnline(string userName)
{
    Hashtable online = (Hashtable)Application["Online"] ?? new Hashtable();
    foreach (DictionaryEntry entry in online)
    {
        if (entry.Value?.ToString() == userName) return false; // 已在線
    }
    return true; // 可登錄
}

// 登錄成功後註冊
Hashtable online = (Hashtable)Application["Online"] ?? new Hashtable();
online[Session.SessionID] = userName;
Application.Lock();
Application["Online"] = online;
Application.UnLock();

// 頁面卸載/Session_End 移除邏輯同上

兩種方案對比

維度Cache 方案Application 方案
性能高 (內建過期掃描)需手動清理過期項
可靠性依賴瀏覽器 onUnload (不可靠)依賴 Session_End (InProc 模式可靠)
擴展性易遷移至 Redis 分布式單機綁定,難擴展
實現複雜度低中

生產環境最佳實踐

  1. 採用分布式 Session (Redis) + 分布式鎖 (Redlock) 實現跨節點互斥登錄。
  2. 登錄時生成 AccessToken 存入 Redis (Key: user:{uid}:token),值含 SessionID、登錄時間、IP。新登錄檢查 Key 是否存在,決定擠下線或拒絕。
  3. 前端 WebSocket/長輪詢監聽「被擠下線」事件,彈窗提示並跳轉登錄頁。
  4. 關鍵操作 (支付、改密) 強制二次驗證,防止 Session 劫持。

上述兩種方案適合單機/小規模部署,理解其核心邏輯「全局唯一標識 + 生命週期管理」有助於向分布式方案演進。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved