最近公司老大叫我實作防止使用者重複登入的功能,既然是老大吩咐的那肯定要去做了,哈哈,開個玩笑,言歸正傳吧。到網上找了很多資料,大部分都用Application或資料庫實作,其原理我就不用多說了,想必大家都知道,一開始想起來很以為很簡單,開始到了後面就很棘手了,為什麼呢,應為用Application或資料庫實作的原理是:當使用者正常登入的時候把使用者名加到Application裡或在資料庫表裡加個字段設定為1表示登入,在使用者退出的時候把Application裡的使用者資訊清除或把資料庫表裡的字段設定成0,但是我們怎麼知道使用者是怎麼樣退出的呢,點浏覽器的x或斷電等等我們都無法把Application裡的使用者資訊清除或把資料庫表裡的字段設定成0。另外有種做法是當使用者正常登入的時候每隔x時間去更新使用者最好活動的時間,然後用時間間隔來判斷使用者是否線上,大于x時間表示使用者退出了(不管是怎麼退出都行),不過這樣的做法對于小型伺服器隻能是望而止步了,應為性能消耗是可想而知的。
我的想法是:既然要防止使用者重複登入,如果有兩個使用者登入了,把前面一個給踢出去那不也符合需求嗎?呵呵
而且這樣也比較好做,不知道大家的想法是不是這樣。現在把代碼貼出來分享下(有些是引用别人寫的)
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace LBC.Web.Modulers
{
///
/// ISingleLogin 接口,提供一組實作單點登入的方法和屬性
///
public interface ISingleLogin
{
///
/// 擷取使用者名
///
string SigleUserLoginId { get; }
///
/// 取消目前會話
///
void SigleUserLogout();
}
///
/// ISingleLoginByCookie接口,提供一組用Cookie實作單點登入的方法和屬性
///
public interface ISingleLoginByCookie : ISingleLogin
{
///
/// 擷取Cookie儲存的值,該值為目前時間的刻度數
///
string CookieValue { get;}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (GetCookieValue("UserId") == "")//為空表示使用者沒有登入
{
Response.Redirect("login.aspx");
}
}
///
/// 擷取Cookie中的值
///
/// 儲存該值的鍵
///
private string GetCookieValue(string KeyName)
{
if (string.IsNullOrEmpty(KeyName)) return "";
if (this.Context.Request.Cookies != null)
{
if (this.Context.Request.Cookies["UserCookie"] != null)
{
HttpCookie cookie = this.Context.Request.Cookies["UserCookie"];
return cookie[KeyName];
}
else
{
return "";
}
}
else
{
return "";
}
}
#region ISingleLogin 成員
///
/// 擷取使用者名
///
public string SigleUserLoginId
{
get
{
return this.GetCookieValue("UserId");//使用者名
}
}
///
/// 取消目前會話
///
public void SigleUserLogout()
{
RemoveCookie();//移除cookie
Session.Abandon();//取消目前會話
Response.Write("你在别處已經登陸,強制退出本次登陸!");
}
///
/// 移除cookie
///
private void RemoveCookie()
{
HttpCookie cookie = new HttpCookie("UserCookie");
cookie.Expires = DateTime.Now.AddDays(-1);
this.Context.Response.Cookies.Add(cookie);
}
#endregion
#region ISingleLoginByCookie 成員
///
/// 擷取Cookie儲存的值,該值為目前時間的刻度數
///
public string CookieValue
{
get
{
return this.GetCookieValue("TimeTick");
}
}
#endregion
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (Session["UserId"] == null)//為空表示使用者沒有登入
{
//Response.Write("你還沒有登陸");
Response.Redirect("login.aspx");
}
}
#region ISingleLogin 成員
///
/// 擷取使用者名
///
public string SigleUserLoginId
{
get
{
return Session["UserId"] == null ? "" : Session["UserId"].ToString();//使用者名
}
}
///
/// 取消目前會話
///
public void SigleUserLogout()
{
Session.Abandon();//取消目前會話
Response.Write("你在别處已經登陸,強制退出本次登陸!");
}
#endregion
}
#region IHttpModule 成員
}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
#endregion
public abstract void context_PreRequestHandlerExecute(object sender, EventArgs e);
}
///
/// 用"Session"實作使用者單點登入的類
///
public class SingleLoginBySession : SingleLoginModuler
{
///
/// 重寫父類的方法
///
///
///
public override void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;//擷取目前HttpApplication對象
IHttpHandler httpHandler = application.Context.CurrentHandler;//擷取目前IHttpHandler對象
ISingleLogin SingleLogin = httpHandler as ISingleLogin;//轉換成ISingleLogin接口,判斷有沒實作該接口
//是否繼承了ISingleLogin接口
if (SingleLogin != null)
{
//目前Session是否存在
if (application.Session != null)
{
//擷取使用者名
string UserId = SingleLogin.SigleUserLoginId;
//使用者是否登入
if (string.IsNullOrEmpty(UserId))
{
//擷取使用者登入的SessionID,在登入頁面設定,并判定兩個ID是否是相同的,不同則表示後來有人用你的帳号登入
if (application.Application["Session" + UserId].ToString() != application.Session.SessionID)
{
//綁定頁面初始化開始時發生的事件
Page page = (Page)httpHandler;
page.PreInit += new EventHandler(page_PreInit);
}
}
}
}
}
///
/// 頁面初始化開始調用的方法
///
///
///
void page_PreInit(object sender, EventArgs e)
{
Page page = sender as Page;
ISingleLogin sl = page as ISingleLogin;
if (sl != null)
{
sl.SigleUserLogout();
page.Response.End();
}
}
}
public override void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;//擷取目前HttpApplication對象
IHttpHandler httpHandler = application.Context.CurrentHandler;//擷取目前IHttpHandler對象
ISingleLoginByCookie SingleLogin = httpHandler as ISingleLoginByCookie;//轉換成ISingleLogin接口,判斷有沒實作該接口
//是否繼承了ISingleLoginByCookie接口且目前Cookies是否存在
if (SingleLogin != null && application.Response.Cookies != null)
{
string UserId = SingleLogin.SigleUserLoginId;//擷取使用者名
string TimeTick = SingleLogin.CookieValue;//擷取目前時間的刻度數
//判斷使用者是否登入且目前時間的刻度數是否為空
if (string.IsNullOrEmpty(UserId) && string.IsNullOrEmpty(TimeTick))
{
return;
}
else
{
if (application.Application["Cookie" + UserId] != null)
{
//擷取使用者登入時儲存在Cookie中的目前時間的刻度數,在登入頁面設定,并判定兩個目前時間的刻度數是否是相同的,
//不同則表示後來有人用你的帳号登入
if (application.Application["Cookie" + UserId].ToString() != TimeTick)
{
//綁定頁面初始化開始時發生的事件
Page page = (Page)httpHandler;
page.PreInit += new EventHandler(page_PreInit);
}
}
}
}
}
///
/// 頁面初始化開始調用的方法
///
///
///
private void page_PreInit(object sender, EventArgs e)
{
Page page = sender as Page;
ISingleLoginByCookie SingleLogin = page as ISingleLoginByCookie;
if (SingleLogin != null)
{
SingleLogin.SigleUserLogout();
page.Response.End();
}
}
}
}
以上是我寫的所有的代碼,用兩種方法實作,本機測試成功