先上幫助類:
/// <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/
