Asp.net 實現只能允許一個賬號同時只能在一個地方登錄


先上幫助類:

/// <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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM