Javascript 不允许同时在多个浏览器/选项卡中登录网站

Javascript 不允许同时在多个浏览器/选项卡中登录网站,javascript,client-server,Javascript,Client Server,我有一个重ajax的网站,当用户同时在多个浏览器窗口中打开它时,它会中断(或显示不正确的数据)。因此,我想强制执行一次只允许用户在一个选项卡中登录网站,无论它是在同一台计算机上还是在多台计算机上 我正在寻找如何做到这一点的想法 是否有JavaScript方法来判断某个页面是否已在另一个选项卡中打开 可能还有另一种解决方案涉及服务器端 例如,客户端可以每隔1分钟向服务器发送一条消息。如果服务器以高于每分钟一条消息的频率从特定用户处获取消息,则它知道它在多个窗口或选项卡中打开。然后,它可以让其中一个

我有一个重ajax的网站,当用户同时在多个浏览器窗口中打开它时,它会中断(或显示不正确的数据)。因此,我想强制执行一次只允许用户在一个选项卡中登录网站,无论它是在同一台计算机上还是在多台计算机上

我正在寻找如何做到这一点的想法

是否有JavaScript方法来判断某个页面是否已在另一个选项卡中打开

可能还有另一种解决方案涉及服务器端

例如,客户端可以每隔1分钟向服务器发送一条消息。如果服务器以高于每分钟一条消息的频率从特定用户处获取消息,则它知道它在多个窗口或选项卡中打开。然后,它可以让其中一个客户端知道它需要向用户喊出一个错误

不过,每一分钟向服务器发送一次消息的想法并不适合我

还有其他想法吗

编辑:有些人想知道我为什么会有这个问题。下面是:
这是一个完全支持ajax的时间跟踪应用程序。您可以使用ajax浏览/创建/删除/修改计时器、项目和客户端,而无需离开页面。如果网站在多个标签页中打开,事情很快就会变得不一致。错误通常甚至会发生。例如,用户创建一个项目,然后在tab1中启动一个计时器,tab2不会显示这些更改。由于它都是ajax,所以当用户单击第二个选项卡中的某个按钮时,它不会简单地同步。

在javascript中无法获取有关其他选项卡/窗口的信息(这是有充分理由的)

我认为最好的方法是在每个页面的javascript代码中打印一个唯一标识符(时间戳应该可以很好地工作),然后定期使用该唯一ID ping服务器,并在服务器上将其与用户关联。这样,如果在给定的时间间隔内ping了一个用户的多个ID,则可以向页面发回响应,警告用户打开多个选项卡将导致意外行为


(就像Caspar在上面所说的,你应该真正弄清楚为什么会发生意外行为,并加以纠正,而不是强迫用户以某种方式行事)

这是相当低的保真度,但我认为简单性可能会让它起作用:你可以尝试让登录名在命名窗口中打开会话(或更改当前窗口的名称). 然后,在应用程序内部加载时,检查浏览器窗口名称是否是您允许他们使用的名称;如果没有,弹出警报,关闭窗口,关注指定的窗口(如果仍然存在)。(如果没有,也就是说,他们已经关闭了另一个窗口,您可以让这个窗口保持打开状态,并将名称更改为正确的名称。)


因此,实际上您使用的是
window.name
window.opener
。大致的想法,但是一个想法。

阅读了您问题中的更新之后,我真正建议的是在可用的情况下使用WebSocket,回到Flash socket,长时间轮询,以及针对较旧浏览器的永久iframe(实际上,我会使这一切变得简单-无论您使用什么环境,都可以使用类似的抽象)。这样,您可以使您的所有窗口和选项卡实时一致-问题得到解决


已经说过,如果你出于某种原因不想这样做(尽管你正在尝试的是一个完美的WebSocket应用程序,请仔细想想),你可以使用sessionStorage和localStorage来区分同一登录用户的选项卡或窗口之间的会话,但是它还没有被广泛使用-请参阅,因此,在有很多可用的回退的情况下,实时使用类似socket.io的解决方案可能比将访问者限制在一个选项卡上更容易,更不用说用户体验了。

我也有类似的情况,我使用的解决方案是:

  • 在服务器上:在每次登录时创建一个唯一的ID,保存它(例如数据库)并将其返回给客户端
  • 在客户机上:在每个事务上,您都将此ID作为参数发送到服务器
  • 在服务器上:如果保存和接收的ID匹配,则允许执行请求,如果不拒绝请求,则返回错误代码
  • 在客户机上:若使用特定代码交易失败,则您知道“ID”验证失败,并且您注销了用户
  • 因此,如果在任何其他选项卡、浏览器、PC、国家/地区中再次使用相同的凭据,。。。旧选项卡将在下一个事务请求时注销用户。或者换句话说,在全世界每个用户只能打开一个页面

    编辑: 由于我已经停止使用html请求进行任何数据通信,并使用WebSocket,所以我在服务器上注册用户,如果同一用户想要从其他位置登录,我将关闭以前使用的套接字(页面将自动注销)。 通过这种方式,我还可以触发服务器重新加载整个页面,以防管理员做了一些影响用户的事情。

    只需使用cookies即可

    $(window).on('beforeunload onbeforeunload', function(){
        document.cookie = 'ic_window_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
    });
    
    function validateCallCenterTab() {
        var win_id_cookie_duration = 10; // in seconds
    
        if (!window.name) {
            window.name = Math.random().toString();
        }
    
        if (!getCookie('ic_window_id') || window.name === getCookie('ic_window_id')) {
            // This means they are using just one tab. Set/clobber the cookie to prolong the tab's validity.
            setCookie('ic_window_id', window.name, win_id_cookie_duration);
        } else if (getCookie('ic_window_id') !== window.name) {
            // this means another browser tab is open, alert them to close the tabs until there is only one remaining
            var message = 'You cannot have this website open in multiple tabs. ' +
                'Please close them until there is only one remaining. Thanks!';
            $('html').html(message);
            clearInterval(callCenterInterval);
            throw 'Multiple call center tabs error. Program terminating.';
        }
    }
    
    callCenterInterval = setInterval(validateCallCenterTab, 3000);
    

    }

    这闻起来像是你试图在一个不应该解决的端点解决一个设计问题。它正在造成赛车状况。但是,为什么您不能修复(或询问)服务器上出现的问题?您的编辑证实了我的怀疑;)。您确实需要在服务器上修复此问题。在输出gui的应用程序中有很多业务逻辑吗?是的,有很多业务逻辑。我想我需要在浏览器上打开一个端口,这样当另一个浏览器选项卡更改某些内容时,服务器可以向浏览器发送消息。我想这很难实现。你可以自己去看看这个网站。。但我不想从这里链接到它。但你可以在这里找到:我刚刚研究了服务器推送,它看起来很复杂。也许服务器轮询是可以的,但有时用户会直接访问wor