因爲項目需要,這兩天一直在嘗試和思考 重複登錄的問題,
想到一些可以思考或者是運用的東西:
Session Application Dictionary MacAddress Cookie 下面將爲什麼考慮要使用這個而做一個分析
Session對象:保存用戶信息如:UserName之類的 這樣方便不同的頁面訪問UserName這樣的對象 而且Session.SessionID 也是一個唯一的 在session過期移除對象的時候作用明顯
AppLication 對象 一個不可少的對象,保存一個在線用戶的一個列表,方便查看該用戶是否已經登錄,現在的狀態是什麼
Dictionary 可以在application中放入dic,方便查詢和存放對象
MacAddress 對象和 Cookie 對象, 這兩個對象我是想的比較深入:假如我們要在不同的瀏覽器中實現一個瀏覽器中登錄了在另外的瀏覽器上還是登錄狀態這樣的想法 我想 MacAddress 和Cookie對象就很有用處了. MacAddress 可以判斷該對象是不是同一臺計算機,而Cookie 可以代替Session存放用戶信息(因爲session跨瀏覽器是得不到值的
)
以上是我思考到的一些碎片 於是開始了整理邏輯和寫代碼
流程上應該是這樣的:
一個用戶[A]到了一個登錄的頁面上,輸入了用戶名和密碼 登錄了,到了一個主頁面. 而有同樣帳號和密碼的另一個用戶[B]在別的計算機也登錄了,到了主頁面,當A刷新的時候出現:您的帳號在別的地方已經登錄了懷疑您的帳號是否被盜用,您將失去訪問權限,請重新登錄並且修改登錄密碼. 這裏需求上說採用踢人的方式進行防止重複登錄
流程清楚了 邏輯也就很明白了;
首先是要申請一個Application 用戶登錄,我們得把這用戶的相關信息放置到session中,方便在主頁面中使用,將 用戶信息和Session.SessionID做一個鍵值對的關係並且放到Dictionary中 判斷Application中是否有該對象[如果有該對象說明這個用戶在別的地方是登錄狀態或者說上一次登錄的狀態還沒有消失(session 還沒有過期程序還沒有移除該對象)]有該用戶 將該用戶從dic中移除,從application中移除此用戶信息. 在重新添加該用戶信息,但現在的信息和以往不同的是:key值不同sessionID 不同
Code:
string userName="";
string userPassword="";
Dictionary<string,string> dic=new Dictionary<string,string>();
//判斷登錄對象是否正確
if (this.TxtUserName.Text!="admin")
{
return;
}
if (this.TxtUserPassword.Text != "admin")
{
return;
}
userName = this.TxtUserName.Text.Trim();
Session["userinfo"] = userName;
//如果登錄成功了
dic.Add(Session.SessionID, userName);
//將對象的信息做一個記錄
if (Application["userinfo"] == null)//如果對象是空對象的話將現有的對象放到app中
{
Application["userinfo"] = dic;
}
else
{
Dictionary<string, string> appdic = new Dictionary<string, string>();
appdic = (Dictionary<string, string>)Application["userinfo"];
//先判斷對象 是否是存在原來的地方
if (appdic.ContainsValue(userName))//如果它有相同的value值說明這個對象原來是有登錄的
{
foreach (string var in appdic.Keys)
{
if (appdic[var]==userName)
{
appdic.Remove(var);//將對象移除,並且break 注:如果不break 程序也許會報一個錯誤:"集合已經修改,可能無法執行枚舉操作"
break;
}
}
//將這個對象代替
}
appdic.Add(Session.SessionID,userName);
Application["userinfo"] = appdic;//將現在的對象放到application中
}
//跳轉到登錄以後的頁面上
Response.Write("<script>location.href='default2.aspx'</script>");
}
以上的代碼是登錄頁面的核心代碼.
在主頁面將要[判斷的是進入主頁面的用戶有沒有登錄,有沒有被踢出.
怎麼判斷呢? 當前登錄的用戶key值和value值能對應就算是
Code:
//先是判斷對象是不是已經登錄狀態了
if (Application["userinfo"] == null || Session["userinfo"] == null)
{
Response.Write("<script>alert('您還沒有登錄,請先登錄')</script>");
return;
}
else//判斷對象中是否已經有這個對象了
{
//判斷對象是否是存在的
Dictionary<string, string> appdic = new Dictionary<string, string>();
appdic = (Dictionary<string, string>)Application["userinfo"];
if (appdic.ContainsKey(Session.SessionID))//如果這個對象是存在的 說明這個對象是登錄過的.
{
//沒問題
LitUserName.Text = Convert.ToString(appdic[Session.SessionID]);
}
else//如果沒找到,說明什麼? 說明
{
//一:這個用戶沒用登錄或者是說這用戶已經過期
Response.Write("<script>alert('您當前登錄已經過期或者在別的地方已經登錄了,請您重新登錄');location.href='default.aspx'</script>");
}
}
在Global文件中唯一要做的就是將過期的session做一個移除
因爲考慮到移除session的不方便處所以就將session.sessionid做爲dic的key,這樣就可以很方便的將該對象做一個移除
Code:
/// <summary>
/// 當session 移除的時候發生
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Session_End(object sender, EventArgs e)
{
// 在會話結束時運行的代碼。
// 注意: 只有在 Web.config 文件中的 sessionstate 模式設置爲
// InProc 時,纔會引發 Session_End 事件。如果會話模式設置爲 StateServer
// 或 SQLServer,則不會引發該事件。
if (Application["userinfo"] != null)
{
System.Collections.Generic.Dictionary<string, string> dic = (System.Collections.Generic.Dictionary<string, string>)Application["userinfo"];
if (dic.ContainsKey(Session.SessionID))//如果包含這個對象 移除這個對象
{
dic.Remove(Session.SessionID);
}
Application["userinfo"] = dic;
}
暫時沒有考慮到相同的計算機上不同的瀏覽器使用問題 先將得到MacAddress的方法貼下以免以後難找:
/// <summary>
/// 這是得到本機編號
/// </summary>
/// <returns></returns>
public string GetNetCardMacAddress()
{
ManagementClass mc;
ManagementObjectCollection moc;
mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
moc = mc.GetInstances();
string str = "";
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"] == true)
str = mo["MacAddress"].ToString();
}
return str;
}