先上帮助类:
/// <summary> /// 单点登录帮助类 /// </summary> public class SSOHelper { /// <summary> /// 登录后执行 /// </summary> /// <param name="UserID">用户标识</param> public void LoginRegister(string UserID) { Hashtable hOnline = (Hashtable)System.Web.HttpContext.Current.Application["Online"]; if (hOnline != null) { IDictionaryEnumerator idE = hOnline.GetEnumerator(); string strKey = ""; while (idE.MoveNext()) { if (idE.Value != null && idE.Value.ToString().Equals(UserID)) { //already login strKey = idE.Key.ToString(); hOnline[strKey] = "XXXXXX"; break; } } } else { hOnline = new Hashtable(); } hOnline[System.Web.HttpContext.Current.Session.SessionID] = UserID; System.Web.HttpContext.Current.Application.Lock(); System.Web.HttpContext.Current.Application["Online"] = hOnline; System.Web.HttpContext.Current.Application.UnLock(); } /// <summary> /// 检查是否唯一登录 /// </summary> /// <returns></returns> public static bool CheckOnline() { Hashtable hOnline = (Hashtable)System.Web.HttpContext.Current.Application["Online"]; if (hOnline != null) { IDictionaryEnumerator idE = hOnline.GetEnumerator(); while (idE.MoveNext()) { if (idE.Key != null && idE.Key.ToString().Equals(System.Web.HttpContext.Current.Session.SessionID)) { //already login if (idE.Value != null && "XXXXXX".Equals(idE.Value.ToString())) { hOnline.Remove(System.Web.HttpContext.Current.Session.SessionID); System.Web.HttpContext.Current.Application.Lock(); System.Web.HttpContext.Current.Application["Online"] = hOnline; System.Web.HttpContext.Current.Application.UnLock(); return false; } break; } } } return true; } /// <summary> /// Global文件的SessionEnd事件中增加此代码 /// </summary> public static void GlobalSessionEnd() { Hashtable hOnline = (Hashtable)System.Web.HttpContext.Current.Application["Online"]; if (hOnline[System.Web.HttpContext.Current.Session.SessionID] != null) { hOnline.Remove(System.Web.HttpContext.Current.Session.SessionID); System.Web.HttpContext.Current.Application.Lock(); System.Web.HttpContext.Current.Application["Online"] = hOnline; System.Web.HttpContext.Current.Application.UnLock(); } } }
在登录的时候调用一下LoginRegister方法
Global.asax中:
protected void Session_End(object sender, EventArgs e) { ltGameStore.Common.SSOHelper.GlobalSessionEnd(); }
剩下的就是在每次客户端对服务器有请求的时候验证当前会话ID是否被注销掉了(被其他用户挤掉)
我用的是一个继承Controller的基类,重写里面的OnAuhorization方法:
/// <summary> /// 在进行授权时调用 /// </summary> /// <param name="filterContext"></param> protected override void OnAuthorization(AuthorizationContext filterContext) { //不能应用在子方法上 if (filterContext.IsChildAction) return; //如果没有登录,则跳转到登录视图 if (WorkContext.Action != "login") { if (!TicketHelper.IsLogin()) { filterContext.Result = new RedirectResult("/Account/login"); } } if (!SSOHelper.CheckOnline()) { filterContext.Result = PromptView("您的账号已在别处登录"); } //如果当前用户不是管理员 //if (WorkContext.AdminGid == 1) //{ // if (WorkContext.IsHttpAjax) // filterContext.Result = new ContentResult { Content = "404" }; // else // filterContext.Result = new RedirectResult("/"); // return; //} }
注意,这样写的话会有个问题,每次客户端请求的SessionID都不一样,这样就无法校验了,搜了一下解决方法,在重写的Initialize方法(继承Controller的基类中)中不断的注册SessionId:
/// <summary> /// 初始化调用构造函数后可能不可用的数据 /// </summary> /// <param name="requestContext"></param> protected override void Initialize(RequestContext requestContext) { base.Initialize(requestContext); Session["SessionId"] = Session.SessionID; }
参考以下:
http://www.cnblogs.com/xlhblogs/archive/2012/03/29/2422804.html
http://czhjq.blog.163.com/blog/static/85014962010112263336615/