防止用户多次登录

一、思路:

1、在sessionState为InProc时,每次新开一个IE窗口,都产生一个新的Session对象,每个Session的ID是唯一的(StateServer维持一个Session,不能利用SessionID);

2、以SessionID为键,登录的用户ID为键值,将用户的登录信息添加进键值对集合,然后保存到Application中;

3、每次登录时,在用户ID和密码验证成功后,检查登录的用户ID是否已存在于集合中,是则取出对应的键,在后面将该键的值置为空;

4、

二、具体实施:

1、在登录页进行处理:

       Dictionary<string, string> dic = null;
            if (Application["LoginInfo"] != null)
            {
                string sessionId = "";//前面已经登录过的用户的SessionID值
                //获取各个已登录用户的登录信息
                dic = (Dictionary<string, string>)Application["LoginInfo"];
                foreach (var item in dic)
                {
                    //用户ID已存在,即用户已经登录
                    if (item.Value == userId)
                    {
                        //取出该条记录的key
                        sessionId = item.Key;
                        break;
                    }
                }

                //当前登录的用户已经登录了,集合的值置为空
                if (!string.IsNullOrEmpty(sessionId))
                {
                    dic[sessionId] = "";
                }
            }
            else
            {
                dic = new Dictionary<string, string>();
            }

            //在集合中为新登录用户存入唯一的SessionID和用户ID
            if (!dic.ContainsKey(Session.SessionID))
            {
                dic.Add(Session.SessionID, userId);
                //存存储登录信息至Application
                Application.Lock();
                Application["LoginInfo"] = dic;
                Application.UnLock();
            }

2、新建一个页面基类,供各个页面继承,在里面添加OnInit()方法进行处理:

namespace outctrl
{
    public class BasePage :System.Web.UI.Page
    {
        protected override void OnInit(EventArgs e)
        {
            if (Application["LoginInfo"] != null)
            {
                //获取已经存储的application值
                Dictionary<string, string> dic = (Dictionary<string, string>)Application["LoginInfo"];
                foreach (var item in dic)
                {
                    //SessionID相同,是当前用户的信息  
                    if (item.Key == Session.SessionID)
                    {
                        //值被置为空,表明用户已经在其他地方登录
                        if (string.IsNullOrEmpty(item.Value))
                        {
                            dic.Remove(Session.SessionID);
                            Application.Lock();
                            Application["LoginInfo"] = dic;
                            Application.UnLock();
                            Response.Write("<script>alert('你的帐号已在别处登陆,你被强迫下线!');top.location.href = '../Login.aspx'</script>");
                            // Response.Redirect("Default.aspx");   
                            Response.End();
                        }
                    }
                }
            }
        }
    }
}

3、设置一个退出页(或直接退出按钮),使用Session.Abandon(),以便结束当前Session对象,并调用Global文件的Session_End事件;

4、在Session_End事件里加入处理程序:

// 在会话结束时运行的代码。 
            // 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
            // InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer 
            // 或 SQLServer,则不会引发该事件。
            //获取已经存储的application值
            if (Application["LoginInfo"] != null)
            {
                Dictionary<string, string> dic = (Dictionary<string, string>)Application["LoginInfo"];
                if (dic.ContainsKey(Session.SessionID))
                {
                    //清除当前SessionID
                    dic.Remove(Session.SessionID);
                    Application.Lock();
                    Application["LoginInfo"] = dic;
                    Application.UnLock();
                }
            }
原文地址:https://www.cnblogs.com/qfcndtt/p/2870107.html