最近公司老大叫我实现防止用户重复登录的功能,既然是老大吩咐的那肯定要去做了,哈哈,开个玩笑,言归正传吧。到网上找了很多资料,大部分都用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;}
}
///
/// 用Cookie实现用户单点登录的类,应继承此类
/// Cookie名称为UserCookie,其中键"UserId"用来保存用户名,"TimeTick"用来保存当前时间刻度数
///
public class BasePageByCookie : System.Web.UI.Page, LBC.Web.Modulers.ISingleLoginByCookie
{
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
}
///
/// 用Session实现用户单点登录的类,应继承此类
///
public class BasePageBySession : System.Web.UI.Page, LBC.Web.Modulers.ISingleLogin
{
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
}
///
/// 单点的登录的抽象类
///
public abstract class SingleLoginModuler : IHttpModule
{
#region IHttpModule 成员
public void Dispose()
{
}
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();
}
}
}
///
///用"Cookie"实现用户单点登录的类
///
public class SingleLoginByCookie : SingleLoginModuler
{
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();
}
}
}
}
以上是我写的所有的代码,用两种方法实现,本机测试成功