代码之家  ›  专栏  ›  技术社区  ›  Pierre-Jean Coudert

如何防止多个浏览器窗口在asp.net中共享同一会话

  •  15
  • Pierre-Jean Coudert  · 技术社区  · 15 年前

    我有一个ASP.net应用程序,它基本上是一个物理检查过程的数据输入屏幕。用户希望能够打开多个浏览器窗口并同时输入来自多个检查的数据。一开始我使用的是基于cookie的会话,很明显这件事搞砸了。

    我转而使用无cookie会话,它将会话存储在URL中,在测试中,这似乎解决了问题。每个浏览器窗口/选项卡都有不同的会话ID,其中一个窗口/选项卡中输入的数据不会与另一个窗口/选项卡中输入的数据发生冲突。

    然而,我的用户比我预期的更有效地打破东西,似乎他们仍然设法获得相同的会话之间的浏览器有时。我认为他们正在将地址从一个选项卡复制/粘贴到另一个选项卡以打开应用程序,但我还无法验证这一点(他们在另一个位置,所以我不能轻易地询问他们)。

    除了告诉他们不要复制和粘贴,或说服他们一次只输入一个,我如何才能防止这种情况发生?

    7 回复  |  直到 15 年前
        1
  •  5
  •   Matthias Meid    11 年前

    考虑使用ViewState而不是Session,因为ViewState将状态信息呈现给客户端(HTML页面)。我不确定您是否能够获得对浏览器会话行为的详细控制,因为会话ID是由浏览器维护的,就像制造商那样。因此,ViewState更易于预测,不仅适用于未来的浏览器版本。

        2
  •  3
  •   John Lim    14 年前

    这是一个很好的问题,我也考虑了很长时间。

    你需要确保你的整个应用程序是iframe友好的。

        3
  •  3
  •   icelava    14 年前

    我不确定您为什么希望将会话限制为只处理一个检查过程,然后强制多个会话以便用户同时处理多个检查。这感觉像是一种相当尴尬的孤立方式。

    无论会话变量中保存的数据是什么,都不应该为单一处理而公开。它们应该存放在 收藏

    伪码概念

    var inspectionID = this.inspectionLabel.Text;
    var inspectionSets = (Hashtable)Session["inspections"];
    var inspection = (Inspection)inspectionSets[inspectionID];
    
        4
  •  2
  •   D'Arcy Rittich    15 年前

    用户必须使用不同的帐户登录才能访问不同的物理检查吗?在我看来只要 PhysicalInspectionID

    例如。,

    http://inspections.mydomain.com/edit/23

        5
  •  2
  •   JustAMartin    12 年前

    这是我在ASP.NET MVC中用来禁止经过身份验证的用户打开多个选项卡的内容:

    <script language="javascript" type="text/javascript">
        @if(Request.IsAuthenticated)
        {
            <text>
            if (window.name != 'singleWindow') {
                window.location.href = "Content/ErrorPages/SingleTab.htm";
            } 
            </text>
        }
        else
        {
            <text>
            window.name = "singleWindow";
            </text>
        }
    </script>
    

    基本上,这会在用户第一次访问登录页面时设置窗口名。登录后,对于每个后续页面加载,都会测试窗口名。

    两个问题:

    • 如果禁用JavaScript,则不工作
    • 如果用户错误地关闭原始选项卡,然后在地址栏中粘贴到我的网站的其他链接,则用户将始终收到错误页面。为了给用户一个恢复的机会,我在SingleTab.htm页面中包含了“注销”链接,这样用户就可以销毁他的会话cookie并启动一个新会话。
        6
  •  2
  •   yazanpro    11 年前

    该问题的解决方案可通过以下方式实现:

    public static class CommonHelper
    {
       public static bool SiteGuard
        {
            get
            {
                if(HttpContext.Current.Session["SiteGuard"] == null)
                   return true;
                return (bool)HttpContext.Current.Session["SiteGuard"];
            }
            set
            {
                HttpContext.Current.Session["SiteGuard"] = value;
            }
        }
    }
    
    public partial class TestPage : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if(!Page.IsPostBack)
            {
                bool go = false;
                for(int i = 0; i < 50; i++) // wait for the service to work (5 secs max)
                {
                    if(CommonHelper.SiteGuard)
                    {
                       go = true;
                       break;
                    }
                    Thread.Sleep(100);
                }
                if(!go)
                   Response.Redirect("Login.aspx");
    
                SiteGuard = false; // from now on, nobody can visit your site
            }
            // Now as long as Page.IsPostBack is true you are in a good shape
        }
    }
    

    将asmx web服务(或您认为合适的任何其他类型的服务)添加到根项目中,并向其添加以下方法:

        [WebMethod(EnableSession = true)]
        public void FreeSiteGuard()
        {
            HttpContext.Current.Session["SiteGuard"] = null;
        }
    

    <script type="text/javascript">
        window.onbeforeunload = function (e) {
            e = e || window.event;
            if (e) {
                // Invoke web service 
               YourProject.YourWebServiceName.FreeSiteGuard();
            }
        };
    </script>
    

    请注意,您的站点响应时间会受到web服务速度的影响。

        7
  •  0
  •   Mike Koder    15 年前

    当请求没有referer时创建一个新sessionId。 这就解决了复制粘贴url的问题。