最近工作压力太大,感觉身体被掏空,每天都疲惫不堪,终于体会到心累的滋味了。原因仅仅是一个来自日本的外包项目,具体就不展开说了,我们今天就盯着一个技术问题来扯。

一般的Web项目,对于帐号重复登录的逻辑上,常见的解决方案是后登陆的把前登录的用户踢掉。这么做很大一定程度上是受限于http协议的本质的。当然,如果你的项目允许同一个帐号多次登录,那更幸福。

然后,世界并不总是美好的,至少日本这个项目不是。对方要求的是若账户已经被登录,再次登录时需要提示该账号正在使用中。其实单纯讲业务,这个要求一点也不过分,很多软件也确实是这么做的。不过,在Web上想这么搞,就很恶心人了。

受限于http的先天条件,项目的服务端session很难毫无时差的和浏览器端进行同步,换句话讲,这是一个分布式的问题。因为客户端和服务端分别保存了会话的一部分,并且还要维护数据状态的一致性。

维护这种一致性,就要求浏览器端在用户出现关闭页面,关闭浏览器,甚至关闭电脑的情况下,能通知服务端以清理session。当然,这里面还没包含电脑死机等非正常情况。

可能有人会说,这也不是做不到哇,浏览器上不是存在了一些事件,用来监听用户的操作行为么?例如:onunload,onbeforeunload等。

一开始我们团队也是这么想的,结果在开发的时候发现,这种类型的事件是存在浏览器兼容性问题的,在chrome下,你是无法甄别出用户是刷新还是关闭页面的。展开来说的话,即便是兼容性最好的onbeforeunload事件,chrome下你也无法得知用户是点击的确定还是取消按钮。

这尼玛就有点悲剧了!~我拿着问题的详细描述去找客户去解释,得到的结论是“我不管那么多,我只看结果”,这个观点让我想CTMLGB。你可能觉得我的问题更多一些,我也不打算详细解释(如果有心情,我会花时间另开一个文章专门介绍一下这个奇葩客户)。

现在,问题已经描述清楚了,如果是你,该怎么办?

老朽中午吃饭的时候想到了一个变通的方案,在这里分享出来,希望能帮助到大家。

问题的核心在于无法区分刷新和关闭Tab。针对这两种情况,前者不应该将session清除,后者应该立刻清除session。而两种截然不同的处理方式由于chrome下是相同的事件监听,我们只能从其它维度下手了。

正常情况下,刷新页面会引发数据重新加载,一定会和服务端进行交互。而关闭tab,则不应该会在几秒钟内再发送任何请求了。基于这个常理,我们 只需要在前端的onbeforeunload事件回调中将该用户的session设置成5秒(延迟时间可以根据实际情况来调整)后到期即可

这样做,在刷新触发前,设置了延迟到期,刷新后由于获取数据而立刻在服务端将该session正常续约。而关闭Tab后由于不会获取数据,该session在5秒中自动过期。

这样就几乎完美的解决了这个问题,别跟我扯淡说5秒中内用户再登录会提示帐号正在使用中,你手速那么快你小弟弟受得了么?!

唉,虽然解决了,但宝宝一点也不开心~~