防止用戶重復登陸系統


很多系統要求防止用戶被重復登陸,我們通常思維是當有用戶重復登陸時要禁止他再登陸進去,
提示他該賬號已經有人在使用中.
然而這樣有個問題很難解決,就是系統很難實時捕捉到該賬號是否還在使用中,
如當用戶非正常退出或者遇到停電等,系統只好等到Session超時后才能知道該賬號已經下線.
在Session超時之前這段時間之內沒有人使用賬號但也沒人再能登陸上去,只能干等着了.

我的解決方法是模仿QQ的被迫下線的功能。只要你QQ號和密碼正確,隨時都可以登陸上去,但是如果
該QQ號此前有人在使用的話那先前的人就會被擠下去。我們這樣來實現系統防止用戶重復登陸的話就可以輕松實現。關鍵就是在Application或數據庫中記錄下在線用戶的SessionID,檢測使用者的SessionID是否和Application中記錄的該用戶ID相對應的SessionID相同,若不相同則提示下線!

用戶登陸成功時用戶ID和SessionID寫入Application中。

public void WriteToApplication( string UserID )
   {
    DataTable dtUserFlagList = new DataTable();
    try
    {
     dtUserFlagList = (DataTable)Application["UserFlagList"];
    }
    catch
    {
     dtUserFlagList = null;
    }

    if( dtUserFlagList == null )
    {
     DataColumn dc0 = new DataColumn("UserID",typeof(System.String));
     DataColumn dc1 = new DataColumn("SessionID",typeof(System.String));

     dtUserFlagList.Columns.Add( dc0 );
     dtUserFlagList.Columns.Add( dc1 );
     dtUserFlagList.Columns.Add( dc2 );

     DataRow drUser = dtUserFlagList.NewRow();
     drUser["UserID"] = UserID; //寫入用戶ID
     drUser["SessionID"] = Session.SessionID;//記錄下SessionID

     dtUserFlagList.Rows.Add( drUser );
    }
    else
    {
     int i = 1;
     foreach( DataRow drUser in dtUserFlagList )
     {
      if( drUser["UserID"].ToString() == UserID )
      {
       drUser["SessionID"] = Session.SessionID;//如果在Application中存在當前用戶ID,則把記錄的SessionID值改為當前的SessionID
       break;
      }
      i++;
     }
     if( i > dtUserFlagList.Rows.Count )
     {
      DataRow drUser = dtUserFlagList.NewRow();
      drUser["UserID"] = UserID; //寫入用戶ID
      drUser["SessionID"] = Session.SessionID;//記錄下SessionID
  
      dtUserFlagList.Rows.Add( drUser );
     }
    }

    Application.Lock();
    Application["UserFlagList"] = dtUserFlagList; //記錄到Application中
    Application.UnLock();

    Session["UserID"] = UserID;//把相關登陸信息寫入Session
   }

 

下一步我們只要檢測Application中記錄的SessionID是否和當前的SessionID相同就可以了
我在這里寫了一個頁面的基類,每個頁面繼承這個類。這個類改寫OnLoad()事件,加入檢測SessionID值

public class PageBase : System.Web.UI.Page
{
public PageBase()
{
   //
   // TODO: 在此處添加構造函數邏輯
   //
}

protected override void OnLoad(EventArgs e)
{
   base.OnLoad (e);
   if( ! IsPostBack )
   {
    if( Session["UserID"] == null )
    {
     Response.Redirect("Login.aspx");//沒有登陸
     return;
    }
    DataTable dtUserFlagList = (DataTable)Application["UserFlagList"];
    foreach( DataRow drUser in dtUserFlagList )
    {
     if( drUser["UserID"].ToString() == Session["UserID"].ToString() )
     {
      if( drUser["SessionID"].ToString() == Session.SessionID )
       break;//SessionID值相同,沒有其他用戶登陸
      else
      {
       Session.Abandon();//SessionID不相同,有人在使用該賬號,被迫下線
       Response.Redirect("ShowError.aspx?action=該賬號已在別處登陸",false);
      }
     }
    }
   }
} 
}

 

當用戶正常退出系統或非正常退出Session超時,在Application中清除該賬號的記錄
以下代碼寫在Global.asax.cs文件Session_End方法中

protected void Session_End(Object sender, EventArgs e)
{
   if( Session["UserID"] == null )
    return;
  
   DataTable dtUserFlagList = (DataTable)Application["UserFlagList"];
   foreach( DataRow drUser in dtUserFlagList )
   {
    if( drUser["UserID"].ToString() == Session["UserID"].ToString() && drUser["SessionID"].ToString() == Session.SessionID )
    {
     //當UserID和SessionID都和退出用戶的值相等時才清除記錄。
     drUser.Delete();
     break;
    }
   }
   dtUserFlagList.AcceptChanges();

   Application.Lock();
   Application["UserFlagList"] = dtUserFlagList; //將更改記錄到Application中
   Application.UnLock();
}

 

以上方法已經在我的系統中實現,在我的系統可以設定某個賬號同時登陸多少人,只是在記錄中多了一個字段amount。
這個方法可能不好的地方就是每訪問一個頁面都要檢測是否SessionID值相等,
不過我覺得讀取Application並不會太大影響系統的效率,這樣可以“實時”地檢測到用戶是否重復登陸

 

摘自:http://hi.baidu.com/netidea/item/65296b3b9778a1fe96f88dd5


免責聲明!

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



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