检测两个浏览器窗口是不是对同一个站点打开
Posted
技术标签:
【中文标题】检测两个浏览器窗口是不是对同一个站点打开【英文标题】:Detect if two browser windows are open to the same site检测两个浏览器窗口是否对同一个站点打开 【发布时间】:2013-10-19 05:33:15 【问题描述】:我正在尝试检测用户是否在一个选项卡中打开了我的网站,然后在另一个选项卡中打开它。这应该会在新打开的选项卡上向用户显示警告。
现在我每秒钟都会向服务器发送一个“保持活动状态”的 ajax 调用。然后,这会使用唯一 ID 在数据库中记录“上次活动”时间。加载新页面时,它会检查该用户(由用户 ID 标识)在过去 2 秒内是否处于活动状态。
这感觉效率很低。当用户刷新页面时,它也表现不佳。 (这需要不到 2 秒)。我已将 2 秒的检查时间比 keepalive 调用长,以允许较慢的连接。
Q) 我是否以正确的方式进行此操作,或者是否有更简单的方法?我听说 Gmail 和 Facebook 可能会做类似的事情,但我找不到他们做这件事的网站功能。 实际代码使用了很多内部函数,所以大致思路如下:
伪代码:
Page load;
[index] php: Save tabsessionid, userid, datecreated, lastactive, phpsessionid into database;
[index] JS: Every second, send tabsessionid to keepalive.php
[keepalive] PHP: Check if another session exists in the last 2 seconds
[keepalive] PHP: If exists -> Return "-1"; else -> return "1";
[keepalive] PHP: Update tabsessionid's last active time.
我已经尝试了一些解决方案 here,但警告新标签,而不是旧标签似乎是降低延迟/时间方面的棘手部分。
【问题讨论】:
我首先想到的是:为什么不使用sessionStorage
并跟踪那里的标签。监听onbeforeunload
事件以了解用户何时关闭了选项卡。
onbeforeunload
足够可靠吗?我在某处读到另一个解决方案,说你不能保证它会及时触发。我还应该提到这需要跨浏览器工作 - 另一个复杂因素。现在将其编辑到我的帖子中。
***.com/questions/3185105/… 就事件而言,这应该足够了。如果我没记错的话,除了 ie7 之外,任何地方都支持 sessionStorage。
对不起,当我说跨浏览器时,我的意思是如果用户在 Chrome 中打开一个标签,然后在 Firefox 中打开一个标签,它也会在 Firefox 中警告他们。试图想出更好的方法来改写问题 D:
我认为你的做法是正确的。 IMO,这是试图在 HTTP 的无状态性质上维护状态的经典问题之一,因此解决方案总是让人感觉很辛苦。但是,您的建议听起来与我过去曾用于解决类似问题的非常相似的解决方案。
【参考方案1】:
我认为你应该使用参数从每个窗口向服务器发送数据(可能是简单的 HEAD 请求),包含用户 uid 和窗口 id(在页面加载时随机生成一次),并检查是否存在具有多个窗口 id 的相同 uid;
看来这是唯一的办法。
【讨论】:
【参考方案2】:我应该说这是对您的问题的不合适的解决方案吗?
即使您找到了一种肮脏的解决方法来阻止人们在您的网站上进行多标签浏览,您也无法击败隐身模式。如果您这样做了,请帮个忙并提交该浏览器的错误报告。
【讨论】:
我记录的用户ID只有在用户登录网站后才可用。这就是我用来识别人的方法。 好的,谢谢你的澄清。这可能会有所帮助:***.com/questions/368653/…【参考方案3】:这只是一个你必须努力的想法:
javascript 变量是选项卡的本地变量,cookie 很常见。您可以给每个选项卡一个 id 并在链接和表单中传递它*。此 ID 将作为活动选项卡 ID 存储在 cookie 中。如果一个选项卡发现它没有设置 ID,并且设置了活动选项卡 ID,它可以使用另一个 cookie 来询问是否还有具有此 ID 的选项卡,或者已关闭(当然,它必须定期检查这个“问”cookie和答案)。确切的实现取决于您想要做什么。
我希望我解释清楚。
编辑:
*有window.name
js属性,可以作为window id使用,不需要到处传。
【讨论】:
【参考方案4】:您应该保留内容的版本,最初为 1,每次提交的修改都会增加。提交的编辑必须包含版本号,该版本号与当前版本号进行比较,如果不匹配,则拒绝编辑。也可以进行 ajax 调用来询问当前版本,并警告用户他的版本已过时。
sql 更新应该如下所示:
UPDATE table SET .... WHERE id = :id AND version = :version
然后检查受影响的行,如果为 0,则存在并发更新。这样您就不会遇到竞态条件。
【讨论】:
以上是关于检测两个浏览器窗口是不是对同一个站点打开的主要内容,如果未能解决你的问题,请参考以下文章