登录成功后,自动踢掉前一个登录用户,松哥第一次见到这个功能,就是在扣扣里边见到的,当时觉得挺好玩的。
自己做开发后,也遇到过一模一样的需求,正好最近的 Spring Security 系列正在连载,就结合 Spring Security 来和大家聊一聊这个功能如何实现。
本文是本系列的第十三篇,阅读前面文章有助于更好的理解本文:
1.需求分析
在同一个系统中,我们可能只允许一个用户在一个终端上登录,一般来说这可能是出于安全方面的考虑,但是也有一些情况是出于业务上的考虑,松哥之前遇到的需求就是业务原因要求一个用户只能在一个设备上登录。
要实现一个用户不可以同时在两台设备上登录,我们有两种思路:
后来的登录自动踢掉前面的登录,就像大家在扣扣中看到的效果。
如果用户已经登录,则不允许后来者登录。
这种思路都能实现这个功能,具体使用哪一个,还要看我们具体的需求。
在 Spring Security 中,这两种都很好实现,一个配置就可以搞定。
2.具体实现
2.1 踢掉已经登录用户
想要用新的登录踢掉旧的登录,我们只需要将最大会话数设置为 1 即可,配置如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()
.csrf().disable()
.sessionManagement()
.maximumSessions(1);
}
maximumSessions 表示配置最大会话数为 1,这样后面的登录就会自动踢掉前面的登录。这里其他的配置都是我们前面文章讲过的,我就不再重复介绍,文末可以下载案例完整代码。
配置完成后,分别用 Chrome 和 Firefox 两个浏览器进行测试(或者使用 Chrome 中的多用户功能)。
Chrome 上登录成功后,访问 /hello 接口。
Firefox 上登录成功后,访问 /hello 接口。
在 Chrome 上再次访问 /hello 接口,此时会看到如下提示:
This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).
可以看到,这里说这个 session 已经过期,原因则是由于使用同一个用户进行并发登录。
2.2 禁止新的登录
如果相同的用户已经登录了,你不想踢掉他,而是想禁止新的登录操作,那也好办,配置方式如下:
@Override
protected void configure(HttpSecurity http) throws Exception {