zoukankan      html  css  js  c++  java
  • 防止用户重复登陆系统

    很多系统要求防止用户被重复登陆,我们通常思维是当有用户重复登陆时要禁止他再登陆进去,
    提示他该账号已经有人在使用中.
    然而这样有个问题很难解决,就是系统很难实时捕捉到该账号是否还在使用中,
    如当用户非正常退出或者遇到停电等,系统只好等到Session超时后才能知道该账号已经下线.
    在Session超时之前这段时间之内没有人使用账号但也没人再能登陆上去,只能干等着了.

    我的解决方法是模仿QQ的被迫下线的功能。只要你QQ号和密码正确,随时都可以登陆上去,但是如果
    该QQ号此前有人在使用的话那先前的人就会被挤下去。我们这样来实现系统防止用户重复登陆的话就可以轻松实现。关键就是在Application或数据库中记录下在线用户的SessionID,检测使用者的SessionID是否和Application中记录的该用户ID相对应的SessionID相同,若不相同则提示下线!

    用户登陆成功时用户ID和SessionID写入Application中。

    public void WriteToApplication( string UserID )
       {
        DataTable dtUserFlagList = new DataTable();
        try
        {
         dtUserFlagList = (DataTable)Application["UserFlagList"];
        }
        catch
        {
         dtUserFlagList = null;
        }
    
        if( dtUserFlagList == null )
        {
         DataColumn dc0 = new DataColumn("UserID",typeof(System.String));
         DataColumn dc1 = new DataColumn("SessionID",typeof(System.String));
    
         dtUserFlagList.Columns.Add( dc0 );
         dtUserFlagList.Columns.Add( dc1 );
         dtUserFlagList.Columns.Add( dc2 );
    
         DataRow drUser = dtUserFlagList.NewRow();
         drUser["UserID"] = UserID; //写入用户ID
         drUser["SessionID"] = Session.SessionID;//记录下SessionID
    
         dtUserFlagList.Rows.Add( drUser );
        }
        else
        {
         int i = 1;
         foreach( DataRow drUser in dtUserFlagList )
         {
          if( drUser["UserID"].ToString() == UserID )
          {
           drUser["SessionID"] = Session.SessionID;//如果在Application中存在当前用户ID,则把记录的SessionID值改为当前的SessionID
           break;
          }
          i++;
         }
         if( i > dtUserFlagList.Rows.Count )
         {
          DataRow drUser = dtUserFlagList.NewRow();
          drUser["UserID"] = UserID; //写入用户ID
          drUser["SessionID"] = Session.SessionID;//记录下SessionID
      
          dtUserFlagList.Rows.Add( drUser );
         }
        }
    
        Application.Lock();
        Application["UserFlagList"] = dtUserFlagList; //记录到Application中
        Application.UnLock();
    
        Session["UserID"] = UserID;//把相关登陆信息写入Session
       }

    下一步我们只要检测Application中记录的SessionID是否和当前的SessionID相同就可以了
    我在这里写了一个页面的基类,每个页面继承这个类。这个类改写OnLoad()事件,加入检测SessionID值

    public class PageBase : System.Web.UI.Page
    {
    public PageBase()
    {
       //
       // TODO: 在此处添加构造函数逻辑
       //
    }
    
    protected override void OnLoad(EventArgs e)
    {
       base.OnLoad (e);
       if( ! IsPostBack )
       {
        if( Session["UserID"] == null )
        {
         Response.Redirect("Login.aspx");//没有登陆
         return;
        }
        DataTable dtUserFlagList = (DataTable)Application["UserFlagList"];
        foreach( DataRow drUser in dtUserFlagList )
        {
         if( drUser["UserID"].ToString() == Session["UserID"].ToString() )
         {
          if( drUser["SessionID"].ToString() == Session.SessionID )
           break;//SessionID值相同,没有其他用户登陆
          else
          {
           Session.Abandon();//SessionID不相同,有人在使用该账号,被迫下线
           Response.Redirect("ShowError.aspx?action=该账号已在别处登陆",false);
          }
         }
        }
       }
    } 
    }

    当用户正常退出系统或非正常退出Session超时,在Application中清除该账号的记录
    以下代码写在Global.asax.cs文件Session_End方法中

    protected void Session_End(Object sender, EventArgs e)
    {
       if( Session["UserID"] == null )
        return;
      
       DataTable dtUserFlagList = (DataTable)Application["UserFlagList"];
       foreach( DataRow drUser in dtUserFlagList )
       {
        if( drUser["UserID"].ToString() == Session["UserID"].ToString() && drUser["SessionID"].ToString() == Session.SessionID )
        {
         //当UserID和SessionID都和退出用户的值相等时才清除记录。
         drUser.Delete();
         break;
        }
       }
       dtUserFlagList.AcceptChanges();
    
       Application.Lock();
       Application["UserFlagList"] = dtUserFlagList; //将更改记录到Application中
       Application.UnLock();
    }

    以上方法已经在我的系统中实现,在我的系统可以设定某个账号同时登陆多少人,只是在记录中多了一个字段amount。
    这个方法可能不好的地方就是每访问一个页面都要检测是否SessionID值相等,
    不过我觉得读取Application并不会太大影响系统的效率,这样可以“实时”地检测到用户是否重复登陆

    摘自:http://hi.baidu.com/netidea/item/65296b3b9778a1fe96f88dd5

  • 相关阅读:
    BZOJ 3531[Sdoi2014]旅行
    BZOJ4998 星球联盟
    BZOJ2959 长跑
    【北京集训D2T3】tvt
    [Bzoj]5343: [Ctsc2018]混合果汁
    HGOI20190810 省常中互测3
    HGOI20190809 省常中互测2
    HGOI20190808 省常中互测1
    组合排列和组合数 学习笔记
    2-SAT (two-statisfiability) 算法 学习笔记
  • 原文地址:https://www.cnblogs.com/luyiwei/p/4142606.html
Copyright © 2011-2022 走看看