用户唯一登录,最新登录挤掉以前的登录,实现踢人.

您所在的位置:网站首页 qq怎么会自己下线 用户唯一登录,最新登录挤掉以前的登录,实现踢人.

用户唯一登录,最新登录挤掉以前的登录,实现踢人.

2023-08-27 01:50| 来源: 网络整理| 查看: 265

最近在做一个功能,要求是这样的:相同的账号,例如admin账号,在A电脑登录成功,然后admin账号在B电脑登录,系统发现admin账号出现了重复登录,A电脑上登录的admin账号就会被退出登录。

流程图:

我的具体实现方式如下:

1、admin账号在A电脑登录某系统,在登录成功之前,查询redis是否存在登录信息,登录信息结构为:key=用户名,value=sessionid,如果存在,用map集合存起来,如果不存在,则往redis存入登录信息,数据结构是:key=用户名,value=sessionid。

2、把sessionid存入cookie中,不设置过期时间,浏览器关闭则失效

3、如果登录不成功,比如密码错误,则把存在redis中的登录信息删除,如果之前就有存在登录信息,则需要还原信息,从第1步中的map中取出临时存储的登录信息还原到redis上。

4、系统检测admin账号是否重复登录,可以使用拦截器,拦截除了登录请求之外的所有请求,判断admin账号是否已经在其他地方登录,如果是,则马上退出登录。如何判断admin账号是否已经在其他地方登录?实现思路:

①、拦截器方法中获取到sessionid,通过账号名获取到redis上面的sessionid;

②、对比两个sessionid,如果不相等,则说明admin账号在其他地方登录了,当前登录即刻退出登录。

5、使用浏览器的sessionid作为判断标准,那么就是同一台电脑里不同浏览器的sessionid就会不一致,意思就是admin账号不能再多个浏览器登录了。

6、session的默认过期时间是30分钟,在springboot的项目中如何设置session的存活时间呢?可以在配置文件中设置,也可以在启动类中加上一下一段代码即可:

//设置session过期时间 @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setSessionTimeout(10800);// 单位为S } }; }

7、我做的项目是springboot+springcloud的系统,有多个模块,就有多个启动tomcat,那么在浏览器在访问A模块的时候得到的sessionid和浏览器访问B模块的时候获取到的sessionid是不一样的。加入登录功能在A模块中,那么redis上的sessionid就是对应A模块服务器的。这就导致了B模块拿到的sessionid和redis上的sessionid不一致,这就导致了不管admin账号是否有重复登录,用户访问B模块的时候,都会退出登录。如何解决这个问题?思路如下:

①、由于系统是在同一个浏览器上面打开的,模块集成在同一个主页中,登录的时候,把在对应A模块的sessionid存在cookie里。

②、其他模块就从cookie里面获取sessionid,就可以实现多个模块使用同一个sessionid了。

8、其实按照第7点那样的做法是有点麻烦了,可以用网关实现拦截器,这样的话就可以不管什么模块,所有的请求都经过拦截器,就可以完美解决问题了,我为什么不这样做?是因为我们系统没有网关,这个后续应该会改进。

思路就是这样,亲测可以达到想要的效果,希望能帮助你们。如果你们有什么更好的建议,欢迎留言赐教。

9、第9点是2019年3月22日添加的,按照以上方法完成开发后,有一个bug,就是正常登录后,如果模块重启了,正常登录的用户就会被踢出登录并提示有异地登录,这样是不对的,提示会让用户产生疑惑.解决这个bug的方法是:

在模块启动完成后清除redis上的ticket标识,这样用户就不会收到错误的提示了,因为出现异地登录提示首先是要ticket通过拦截器,如果ticket都不存在了,就无法通过拦截器,也就不存在异地登录的提示了.直接让用户重新登录就好.

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3