none
Asp.net中实现同一用户名不能同时登陆(单点登陆) Bug RRS feed

  • 问题


  • 由于需求是同一个帐号如果后者登录,前者将被强行踢出,不可以记录ip方式来实现,问题是我测试我开2个ie ,第一个ie登录。成功登录,然后

    在开一个ie 访问登录页,成功登录。此时刷新ie 1 提示帐号在别处登录,强行踢出,以上测试没问题。

    如果开3个ie ,以下简称ie 1,ie 2,ie 3.测试方式如下。ie 1访问登录,成功登录,ie 2 粘贴ie 1登录后地址

    (defualt2.aspx),ie 3粘贴登录后地址(defualt2.aspx).这时把ie 3地址改成登录入口地址default.aspx 点击登录成

    功登录。然后回到ie 1刷新。正常提示被迫登录,强行退出。回到ie 2 刷新 按理来说ie 2也应该显示被迫登录,强行

    退出,可是问题就出在这里,ie 2刷新没有任何反映。反复测试。只要ie开启2个以上 程序就有bug。代码如下,请教
    不知问题出在那里。郁闷!~!~

    default.aspx 前台页
    
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
    
    transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>无标题页</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:TextBox ID="TextBox1" runat="server">1</asp:TextBox>
            <asp:TextBox ID="TextBox2" runat="server">2</asp:TextBox>
            <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /></div>
        </form>
    </body>
    </html>
    default.aspx.cs(登录页)
    
    public partial class _Default : CommandPage
    {
        
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            if (this.TextBox1.Text == "1" && this.TextBox2.Text == "2")
            {
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    string strKey = "";
                    while (idE.MoveNext())
                    {
                        if (idE.Value != null && idE.Value.ToString().Equals(this.TextBox1.Text))
                        {
                            //already login 
                            strKey = idE.Key.ToString();
                            hOnline[strKey] = "XXXXXX";
                            break;
                        }
                    }
                }
                else
                {
                    hOnline = new Hashtable();
                }
    
                hOnline[HttpContext.Current.Session.SessionID] = this.TextBox1.Text;
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
                Session["id"] = this.TextBox1.Text;
                Response.Redirect("Default2.aspx");
            }
        }
    }
    
    Default2.aspx 成功登录后跳转页
    
    public partial class Default2 : CommandPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
                Response.Write("你已经在线,如果你打开一个新的浏览器访问default.aspx 输入用户名1 密码2你将被
    
    剔除");
        }
    }
    
    CommandPage.cs基类
    
    public class CommandPage:System.Web.UI.Page
    {
    	public CommandPage()
    	{
    		//
    		//TODO: 在此处添加构造函数逻辑
    		//
    	}
        protected override void OnInit(EventArgs e)
        {
            Hashtable hOnline = (Hashtable)Application["Online"];
            if (hOnline != null)
            {
                IDictionaryEnumerator idE = hOnline.GetEnumerator();
                while (idE.MoveNext())
                {
                    if (idE.Key != null && idE.Key.ToString().Equals(Session.SessionID))
                    {
                        //already login
                        if (idE.Value != null && "XXXXXX".Equals(idE.Value.ToString()))
                        {
                            hOnline.Remove(Session.SessionID);
                            Application.Lock();
                            Application["Online"] = hOnline;
                            Application.UnLock();
                            Response.Write("<script>alert('你的帐号已经在别处登录,你已经被退
    
    出');location='default.aspx'</script>");
                            return;
                        }
                        break;
                    }
                }
            }
           
        }
        //protected override void OnLoad(EventArgs e)
        //{
        //    base.OnLoad(e);
        //    if (Session["Id"] == null)
        //    {
        //        Response.Write("你还没有登陆");
        //        Response.Redirect("default.aspx");
        //    }
        //}
    }













    2009年12月17日 15:08

答案

  • 你好,

    我上面的的确不是后者踢掉前者。

    既然是单点登录,那干嘛要让后者踢掉前者。如果用户已经登录,那干脆就不让他再登录了。我觉得这样逻辑似乎更合理点。
    如果你希望能完全实现你的要求,可以试试下面的代码。我的代码在IE8中已经测试过了。在IE8中测试时需要在File菜单下点击New Session(新会话)测试才能成功。
    似乎IE8里新开窗口并不代表是新会话。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Collections;
    
    public partial class SingleLogin : TestPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
           
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    string strKey = "";
                    while (idE.MoveNext())
                    {
                        if (idE.Value != null && idE.Value.ToString().Equals(this.TextBox1.Text))
                        {
                            strKey = HttpContext.Current.Session.SessionID.ToString();
                            hOnline[strKey] = this.TextBox1.Text;
                            Session["id"] = this.TextBox1.Text;
                           //string script = string.Format("<script>alert(\"{0}\");window.location =\"{1}\";</" + "script>", "你的帐号已经在别处登录,你已经被退踢出", "Default.aspx");
                           //ScriptManager.RegisterStartupScript(this,this.GetType(),"test",script,false);
                            return ;
    
                        }
                    }
                }
                else
                {
                    hOnline = new Hashtable();
                }
                hOnline[HttpContext.Current.Session.SessionID] = this.TextBox1.Text;
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
                Session["id"] = this.TextBox1.Text;
    
          
        }
    
    }
    
    
    
    public class TestPage : Page
    {
        protected override void OnInit(EventArgs e)
            {
                Hashtable hOnline = (Hashtable)Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    while (idE.MoveNext())
                    {
                        if (idE.Key != null &&!Session.SessionID.Equals(idE.Key.ToString()))//
                        {
                            //already login
                            if (idE.Value != null && idE.Value.ToString().Equals(Session["id"]))// 
                            {
                                hOnline.Remove(Session.SessionID);
                                Application.Lock();
                                Application["Online"] = hOnline;
                                Application.UnLock();
                                Response.Write("<script>alert('你的帐号已经在别处登录,你已经被退出');location='DivDemo.aspx';</" + "script>");
                                Response.End();
                               
                            }
                            
                        }
                    }
                }
    
    
            }
    }
    

    Microsoft Online Community Support
    • 已标记为答案 ckdrjf 2009年12月25日 6:43
    2009年12月24日 9:22

全部回复

  • 你好,

    你每次运行IE,就会启动一个IE的进程。这样每次都会产生一个SessionID。你在OnInit里面比较SessionID会有问题的。
    Microsoft Online Community Support
    2009年12月21日 7:15
  • 你好 KeFang Chen
    终于有邮件通知,有人回复我发的帖子.感谢回复.
    那我应该在那个事件比较合理那.开2个ie是没问题的.因为这个例子也是网上找的.测试的时候发现的bug
    2009年12月21日 7:34
  • 对不起,不知道为什么我没收到你的回复通知,所以回答晚了。
    其实根据你的需求,你的基类CommandPage中没必要进行判断,所有的工作都可以在登录页面中完成。 然后你把你的登录页面做稍许修改即可。即仅检测用户名,如果该用户名存在了,就不允许再登录,不管sessionid如何。
     protected void Button1_Click(object sender, EventArgs e)
        {
            if (this.TextBox1.Text == "1" && this.TextBox2.Text == "2")
            {
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    string strKey = "";
                    while (idE.MoveNext())
                    {
                        if (idE.Value != null && idE.Value.ToString().Equals(this.TextBox1.Text))
                        {
                           Response.Write("<script>alert('你的帐号已经在别处登录,你已经被退踢出');location='default.aspx'</script>");
    ;
                        }
                    }
                }
                else
                {
                    hOnline = new Hashtable();
                }
    
                hOnline[HttpContext.Current.Session.SessionID] = this.TextBox1.Text;
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
                Session["id"] = this.TextBox1.Text;
                Response.Redirect("Default2.aspx");
            }
        }
    



    当在其它地方需要检验是否登录时就需要比较sessionid和user name.这时如果sessionid与idE.Key.ToString()不相等,那就说明当前sessionid对应的用户没登录,不允许其做某些操作即可。

    Microsoft Online Community Support
    2009年12月23日 6:16
  • KeFang Chen 呵呵 没关系的持点和晚点回复都没关系.
    我按照你提供的代码修改了.可是原本我多开2个ie是可以正常踢掉前者,可是用来你代码,都失灵了.如果方便话,可以把我修改的代码发给你,你看下嘛
    2009年12月23日 7:41
  • 你好,

    不好意思,上面代码有点问题。你试试下面的代码。

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
        protected void Button1_Click(object sender, EventArgs e)
        {
            if (this.TextBox1.Text == "1" && this.TextBox2.Text == "2")
            {
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    while (idE.MoveNext())
                    {
                        if (idE.Value != null && idE.Value.ToString().Equals(this.TextBox1.Text))
                        {
                            string script = string.Format("<script>alert(\"{0}\");window.location =\"{1}\";</" + "script>", "你的帐号已经在别处登录,你已经被退踢出", "Default.aspx");
                            ScriptManager.RegisterStartupScript(this,this.GetType(),"test",script,false);
                            return;
    
                        }
                    }
                }
                else
                {
                    hOnline = new Hashtable();
                }
                hOnline[HttpContext.Current.Session.SessionID] = this.TextBox1.Text;
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
                Session["id"] = this.TextBox1.Text;
               
            }
        }
    
        //protected void Page_Load(object sender, EventArgs e)
        //{
        //    if (!this.IsPostBack)
        //    {
        //         HttpContext.Current.Application["Online"] = null;
        //    }
           
        //}
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        
      
    </head>
    <body>
        <form id="form1" runat="server">
          <script type="text/javascript" language="javascript">
    
        
        </script>
        <div>
        
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
            <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
        
        </div>
        </form>
    </body>
    </html>
    

    Microsoft Online Community Support
    2009年12月23日 8:34
  • hello KeFang Chen
    测试你的代码。打开一个浏览器登录成功登录进入default2.aspx ,然后在开一个浏览器登录,就登录不进去了。这样就并不是后者登录把前者踢掉了。

    protected void Button1_Click(object sender, EventArgs e)
        {
            if (this.TextBox1.Text == "1" && this.TextBox2.Text == "2")
            {
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    while (idE.MoveNext())
                    {
                        if (idE.Value != null && idE.Value.ToString().Equals(this.TextBox1.Text))
                        {
                            string script = string.Format("<script>alert(\"{0}\");window.location =\"{1}\";</" + "script>", "你的帐号已经在别处登录,你已经被退踢出", "Default.aspx");
                            ScriptManager.RegisterStartupScript(this, this.GetType(), "test", script, false);
                            return;
    
                        }
                    }
                }
                else
                {
                    hOnline = new Hashtable();
                }
                hOnline[HttpContext.Current.Session.SessionID] = this.TextBox1.Text;
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
                Session["id"] = this.TextBox1.Text;
                Response.Redirect("Default2.aspx");
    
            }
    
        }
    Global.asax
    
    <%@ Application Language="C#" %>
    
    <script runat="server">
    
        void Application_Start(object sender, EventArgs e) 
        {
            // 在应用程序启动时运行的代码
    
        }
        
        void Application_End(object sender, EventArgs e) 
        {
            //  在应用程序关闭时运行的代码
    
        }
            
        void Application_Error(object sender, EventArgs e) 
        { 
            // 在出现未处理的错误时运行的代码
    
        }
    
        void Session_Start(object sender, EventArgs e) 
        {
            // 在新会话启动时运行的代码
    
        }
    
        void Session_End(object sender, EventArgs e) 
        {
            // 在会话结束时运行的代码。 
            // 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
            // InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer 
            // 或 SQLServer,则不会引发该事件。
    
            Hashtable hOnline = (Hashtable)Application["Online"];
            if (hOnline[Session.SessionID] != null)
            {
                hOnline.Remove(Session.SessionID);
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
            }
        }
           
    </script>
    
    //Default2.aspx
    
    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    public partial class Default2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
                Response.Write("你已经在线,如果你打开一个新的浏览器访问default.aspx 输入用户名1 密码2你将被剔除");
        }
    }
    2009年12月23日 11:09
  • 你好,

    我上面的的确不是后者踢掉前者。

    既然是单点登录,那干嘛要让后者踢掉前者。如果用户已经登录,那干脆就不让他再登录了。我觉得这样逻辑似乎更合理点。
    如果你希望能完全实现你的要求,可以试试下面的代码。我的代码在IE8中已经测试过了。在IE8中测试时需要在File菜单下点击New Session(新会话)测试才能成功。
    似乎IE8里新开窗口并不代表是新会话。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Collections;
    
    public partial class SingleLogin : TestPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
           
                Hashtable hOnline = (Hashtable)HttpContext.Current.Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    string strKey = "";
                    while (idE.MoveNext())
                    {
                        if (idE.Value != null && idE.Value.ToString().Equals(this.TextBox1.Text))
                        {
                            strKey = HttpContext.Current.Session.SessionID.ToString();
                            hOnline[strKey] = this.TextBox1.Text;
                            Session["id"] = this.TextBox1.Text;
                           //string script = string.Format("<script>alert(\"{0}\");window.location =\"{1}\";</" + "script>", "你的帐号已经在别处登录,你已经被退踢出", "Default.aspx");
                           //ScriptManager.RegisterStartupScript(this,this.GetType(),"test",script,false);
                            return ;
    
                        }
                    }
                }
                else
                {
                    hOnline = new Hashtable();
                }
                hOnline[HttpContext.Current.Session.SessionID] = this.TextBox1.Text;
                Application.Lock();
                Application["Online"] = hOnline;
                Application.UnLock();
                Session["id"] = this.TextBox1.Text;
    
          
        }
    
    }
    
    
    
    public class TestPage : Page
    {
        protected override void OnInit(EventArgs e)
            {
                Hashtable hOnline = (Hashtable)Application["Online"];
                if (hOnline != null)
                {
                    IDictionaryEnumerator idE = hOnline.GetEnumerator();
                    while (idE.MoveNext())
                    {
                        if (idE.Key != null &&!Session.SessionID.Equals(idE.Key.ToString()))//
                        {
                            //already login
                            if (idE.Value != null && idE.Value.ToString().Equals(Session["id"]))// 
                            {
                                hOnline.Remove(Session.SessionID);
                                Application.Lock();
                                Application["Online"] = hOnline;
                                Application.UnLock();
                                Response.Write("<script>alert('你的帐号已经在别处登录,你已经被退出');location='DivDemo.aspx';</" + "script>");
                                Response.End();
                               
                            }
                            
                        }
                    }
                }
    
    
            }
    }
    

    Microsoft Online Community Support
    • 已标记为答案 ckdrjf 2009年12月25日 6:43
    2009年12月24日 9:22
  • 你好.KeFang Chen 感谢回复.
    测试,还是有很多问题.,我这边登录,其他人在登录这个号码.没反映也没成功登录,我这边刷新缺本弹出,脚本框无法关闭等,咳...搞的这个例子有点头晕,可能我描述的你没明白.但是还是感谢你一直回复,和提供解决代码.结贴了.
    谢了.
    能否留下Live
    2009年12月25日 6:43
  • 好的,我的Live:chenkefang1216@163.com

    有什么问题我们再说。
    Microsoft Online Community Support
    2009年12月25日 6:47