代码之家  ›  专栏  ›  技术社区  ›  Ryan Emerle

阻止同一服务器会话上的多个浏览器会话

  •  6
  • Ryan Emerle  · 技术社区  · 15 年前

    我敢肯定,我们都在努力工作,或者都知道Web应用程序(特别是在企业中)已经与服务器会话紧密地绑定在一起。在这些情况下,如果打开多个浏览器会话并使用同一服务器会话cookie,会话可能会损坏。我们已经研究了所有选项,并发现向前推进的最佳方法是不鼓励使用共享服务器会话cookie的多个浏览器会话。

    只有当用户执行 New Window - Ctrl+N 在IE中或其他浏览器中的“复制标签”。本质上,我们最终得到两个活动的浏览器会话,共享相同的cookie。

    所以,为了阻止这种行为(因为这很可能是无意的),我开始设置某种警告系统来防止这种行为。现在,我们的代码进行了大量的并发检查以确保数据完整性,但是仍然存在数据损坏的问题。

    我的解决方案是,在发现一般的答案是“不可能”之后,依靠Ajax发送“ping”并测量两者之间的时间间隔。所以,我们有一个一般规则:我们在某个时间间隔“ping”,如果当前ping中最后一个ping之间的增量是 较少的 与ping持续时间相比,我们知道在一个服务器会话上有多个活动的浏览器会话。

    所以,在哪里 Pf 是ping频率; Pc 是当前ping;并且 Pl 是最后一次Ping,那么当 Pf > (Pc - Pl) .

               p1    p2    p3    p4
    TAB1 0-----|-----|-----|-----|---...
                     :     :     :
                     :  p1 :  p2 :  p3    p4
    TAB2          0-----|-----|-----|-----|---...
         ^     ^     ^  ^  ^  ^  ^  ^
                      Deltas
    
    ----+---+------------
    TAB | P |   Delta (Pc - Pl)
    ----+---+------------                 
     1  | 1 |   5
     1  | 2 |   5
     2  | 1 |   2.5 -Error
     1  | 3 |   2.5 -Error
     2  | 2 |   2.5 -Error
    

    现在,如果存在网络拥塞或其他因素,那么delta将是 更大的 比频率高,排除误报。

    如果两个标签在完全相同的时间打开,我们确实会遇到问题。但是,由于ping频率只是请求的频率,而不是保证的运行时间,因此我们可以假设很快两个浏览器会话就会开始不同步。

    在这个例子中,我将ping频率设置为每5秒一次。如果有100个同时使用的用户,那么对于ping servlet/http模块,我们将以大约20个请求/秒的速度查找。为了减少不必要的网络流量,我认为ping频率会随着时间的推移而衰减,直到达到最大20 ping/秒。这相当于每秒约5个请求,有100个并发用户。不过,这是一种权衡,因为它会导致检测延迟。但是,一旦检测到,频率重置为5 Ping/秒,直到解决。(这些数字只是一个例子;它们会根据环境变化a)

    为了最小化并发性和可伸缩性问题,会话的最后一个ping时间戳应该保存在会话本身中。这将允许任何分布式会话技术在JVM或应用程序域之间保持会话的可用性,而不需要我们的ping服务知道它。

    我正在试图确定这是否是一个合理的方法,如果我在一个受伤的世界。任何关于这个问题的经验都是有益的。

    编辑: 我知道这听起来像是一个创可贴,但这是一个权宜之计,直到我们可以撕掉冒犯图书馆。

    7 回复  |  直到 11 年前
        1
  •  2
  •   Matthew    15 年前

    多年前,我在一个单窗口的Web应用程序上工作(预约会“Web2.0”)。我们只是启动了一个没有任何工具栏(没有后退按钮等)的新窗口,并禁用了右键单击。我们注意到创建了一个非常有用的会话导航系统。这足以防止几乎所有意外的重复浏览。这是一个内部网应用程序;很明显,我从不建议在一个普通的网站上做类似的事情。

    就我个人而言,我不喜欢ping探测器的声音。我只是确保不会发生数据损坏。多个浏览器会话不是有效的借口…尽管我知道这会有什么问题。但是,如果您想在完美工作的代码之上添加一个ping检测器,那么它可能会对用户起到一个有用的提醒作用。

    您可以在每个链接的末尾添加一个唯一的标记。如果唯一令牌被多次使用(例如,打开一个新窗口、书签、后退、前进),那么请求可能被拒绝。通过适当的跟踪,您可以确保在不使用有效路径的情况下,永远不可能从一个页面访问另一个页面。这种方法比ping更可靠(因为它由服务器控制),但可能会导致非常烦人的用户体验。

    它的缺点是:修复应用程序以避免损坏任何数据。我知道这可能不是一件小事,我也不想轻视它。执行ping和类似的操作可能有助于使问题消失,但我向您保证,如果出现问题,最终会出现问题。-)

        2
  •  2
  •   ThiefMaster    12 年前

    用户使用什么浏览器?
    当IE8出现时,我们解决了一个数据损坏解决方案,并提供了 NoMerge 选项。

        3
  •  2
  •   Dave E    12 年前

    您可以使用在客户机上创建的javascript和cookie,结合浏览器/dom窗口名必须是唯一的这一事实来实现这一点。很容易使用而不改变你的网站。

    1) 第一次加载页面时,请检查会话cookie是否存在,如果不存在,请使用唯一的名称和值(某种代码)创建会话cookie(不要设置到期日期)。使用此cookie值设置浏览器/dom窗口名(而不是标题)。

    2) 在随后的请求中,您需要检查dom窗口名称是否与cookie值相同-如果不重定向到错误页。

    3) 记住在页面卸载时删除cookie,这样关闭窗口会删除cookie。

    这是因为如果您尝试打开一个重复的窗口,该重复的窗口将不会具有与cookie值相同的窗口dom名称,并且您可以响应这个事实。

    代码示例

    function CheckMultipleSession() {
    var existingCookieValue = getCookie("MySessionCookie");
    if (existingCookieValue == null) { //first request so create cookie
       currentCookieValue = guid();
       setCookie("SessionGUID", currentCookieValue); 
       window.name = currentCookieValue; // setting DOM window name (this is key)
    }
    else {
    if (existingCookieValue != window.name)
       top.location = "MultipleSessionsError.htm";                                       
    }
    }
    
        4
  •  1
  •   Jon    15 年前

    我主要关心的是,当存在网络延迟时,这是否会受到影响。也就是说,任何问题都可能来自于通常首先使用ping的问题。

        5
  •  1
  •   Bryan Batchelder    15 年前

    如果您真的处于绑定状态,并且无法修复应用程序以正常处理共享同一会话的多个浏览器实例,那么是的,这是一种很好的方法。

    就其价值而言,我使用了完全相同的概念来强制并发使用许可证约束——因此它将检测到共享同一“密钥”的多个用户,在您的情况下,这就是会话。

    我只会稍微修改您的方法,让ping消息包含客户端的日期/时间,这样您就可以避免在计算中处理网络延迟。

        6
  •  1
  •   user883986    13 年前

    今天太迟了。但您可能希望考虑在服务器上生成一个随机字符串并以隐藏的形式将其发送到前端的选项。在用户的会话对象中维护会话的最后一个随机键。每次用户向服务器发出请求时,都会将此随机密钥发回。检查浏览器中存储在会话中的随机键。如果它们不匹配,那么您可以告诉用户应该使用另一个窗口。对用户不太友好,但可以。

        7
  •  0
  •   GreenieMeanie    15 年前

    对于Ajax应用程序,一个可能或可能无法使用的非常简单的解决方案是有一个页面(即一个URL,如home.whatever)。如果他们再次请求同一页,并且已经有一个有效的会话,那么您知道他们打开了一个新的选项卡或一个新窗口。但是,请注意,您将无法将其与刷新区分开来。

    你的解决方案太复杂了。