Asp.net MVC 用户在线简单实现及单点登陆扩展(一)
首先,让我们想来思考如何实现在线用户的统计,这里我将使用IHttpModule扩展我们的在线用户模块。
创建我们需要的实体类
代码
public class OnlineUser
{
/// <summary>
/// 登录用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 登陆时间
/// </summary>
public DateTime LoginTime { get; set; }
/// <summary>
/// 最后一次活动时间
/// </summary>
public DateTime LastTime { get; set; }
/// <summary>
/// 最后一次活动地址
/// </summary>
public string LastActionUrl { get; set; }
/// <summary>
/// 登陆IP地址
/// </summary>
public string LoginIp { get; set; }
/// <summary>
/// 是否为游客
/// </summary>
public bool IsGuest { get; set; }
/// <summary>
/// 当前会话ID
/// </summary>
public string SessionID { get; set; }
}
{
/// <summary>
/// 登录用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 登陆时间
/// </summary>
public DateTime LoginTime { get; set; }
/// <summary>
/// 最后一次活动时间
/// </summary>
public DateTime LastTime { get; set; }
/// <summary>
/// 最后一次活动地址
/// </summary>
public string LastActionUrl { get; set; }
/// <summary>
/// 登陆IP地址
/// </summary>
public string LoginIp { get; set; }
/// <summary>
/// 是否为游客
/// </summary>
public bool IsGuest { get; set; }
/// <summary>
/// 当前会话ID
/// </summary>
public string SessionID { get; set; }
}
然后我们来实现我们的IHttpModule
代码
public class UserOnlineModule : IHttpModule
{
#region IHttpModule 成员
public static List<Models.OnlineUser> OnlineList = null;
private System.Timers.Timer updateTimer;
//在线用户活动超时:分钟,默认10分钟
private int timeOut = 10;
//设置计时器触发周期:毫秒,默认1分钟
private double timeInterval = 60000;
public void Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
}
void context_AuthenticateRequest(object sender, EventArgs e)
{
if (OnlineList == null)
OnlineList = new List<Models.OnlineUser>();
updateTimer = new System.Timers.Timer();
updateTimer.AutoReset = true;
updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed);
updateTimer.Interval = timeInterval;
updateTimer.Start();
}
void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
updateTimer.Stop();
if (OnlineList.Count > 0)
OnlineList.RemoveAll(p => (DateTime.Now - p.LastTime).Minutes >= timeOut);
updateTimer.Interval = timeInterval;
updateTimer.Start();
}
public void Dispose()
{
}
#endregion
}
{
#region IHttpModule 成员
public static List<Models.OnlineUser> OnlineList = null;
private System.Timers.Timer updateTimer;
//在线用户活动超时:分钟,默认10分钟
private int timeOut = 10;
//设置计时器触发周期:毫秒,默认1分钟
private double timeInterval = 60000;
public void Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
}
void context_AuthenticateRequest(object sender, EventArgs e)
{
if (OnlineList == null)
OnlineList = new List<Models.OnlineUser>();
updateTimer = new System.Timers.Timer();
updateTimer.AutoReset = true;
updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed);
updateTimer.Interval = timeInterval;
updateTimer.Start();
}
void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
updateTimer.Stop();
if (OnlineList.Count > 0)
OnlineList.RemoveAll(p => (DateTime.Now - p.LastTime).Minutes >= timeOut);
updateTimer.Interval = timeInterval;
updateTimer.Start();
}
public void Dispose()
{
}
#endregion
}
对,就这么简单的一个IHttpModule实现,只不过是一个设置了一个简单的定时器,每分钟执行一次RemoveAll操作,下面我们来定义一个ActionFilter,为需要实现在线用户记录的页面添加(因为实际项目中一些页面并不需要去)
代码
public class OnlineFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string findName = filterContext.HttpContext.User.Identity.Name;
bool isGuest = false;
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
findName = filterContext.HttpContext.User.Identity.Name;
else
{
findName = filterContext.HttpContext.Session.SessionID.ToUpper();
isGuest = true;
}
Models.OnlineUser userModel = UserOnlineModule.OnlineList.Find(p =>
p.UserName.Equals(findName, StringComparison.CurrentCultureIgnoreCase));
if (userModel == null)
{
userModel = new Models.OnlineUser();
userModel.UserName = findName;
userModel.LoginTime = DateTime.Now;
userModel.LastTime = DateTime.Now;
userModel.LoginIp = filterContext.HttpContext.Request.UserHostAddress;
userModel.LastActionUrl = filterContext.HttpContext.Request.Url.PathAndQuery;
userModel.SessionID = filterContext.HttpContext.Session.SessionID.ToUpper();
userModel.IsGuest = isGuest;
UserOnlineModule.OnlineList.Add(userModel);
}
else
{
userModel.LastTime = DateTime.Now;
userModel.LastActionUrl = filterContext.HttpContext.Request.Url.PathAndQuery;
}
}
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string findName = filterContext.HttpContext.User.Identity.Name;
bool isGuest = false;
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
findName = filterContext.HttpContext.User.Identity.Name;
else
{
findName = filterContext.HttpContext.Session.SessionID.ToUpper();
isGuest = true;
}
Models.OnlineUser userModel = UserOnlineModule.OnlineList.Find(p =>
p.UserName.Equals(findName, StringComparison.CurrentCultureIgnoreCase));
if (userModel == null)
{
userModel = new Models.OnlineUser();
userModel.UserName = findName;
userModel.LoginTime = DateTime.Now;
userModel.LastTime = DateTime.Now;
userModel.LoginIp = filterContext.HttpContext.Request.UserHostAddress;
userModel.LastActionUrl = filterContext.HttpContext.Request.Url.PathAndQuery;
userModel.SessionID = filterContext.HttpContext.Session.SessionID.ToUpper();
userModel.IsGuest = isGuest;
UserOnlineModule.OnlineList.Add(userModel);
}
else
{
userModel.LastTime = DateTime.Now;
userModel.LastActionUrl = filterContext.HttpContext.Request.Url.PathAndQuery;
}
}
对了,忘记一个很重要的事,那就是注册我们的IHttpModule,打开Web.config页面,找到<httpModules>节,添加
<add name="OnlineList" type="命名空间.UserOnlineModule"/>
就这么简单的实现了在线用户的统计,现在来看看使用
[OnlineFilter]
public ActionResult Index(string id)
{
return View();
}
public ActionResult Index(string id)
{
return View();
}
你可以这样简单的在Action上进行Filter的标注,如果你有一个Controller都需要进行在线统计,那么你可以直接在整个Controller上标注一个就可以了。很简单吧。
下一篇将介绍一下利用这个简单的在线用户实现进行单点登陆限制,其实很多朋友可能已经知道该怎么做了。