springSecurity限制多用户登录

springSecurity限制多用户登录

​ 限制用户多次登录的原理就是,每次用户登录时,将用户的sessionId存储起来,下次在登录时检查已经存在的sessionId列表里此用户登陆了几次,就能据此做处理了。

​ 最简单的就像这样设置,这样做以后后面登录的会将前面最近未使用的session挤掉。

1
http.sessionManagement().maximumSessions(1);

​ 如果想要禁止后面人的登录,而不是挤掉前面的人,可以这么做。可以拒绝后面登录的请求。这么做前面的人只是关闭浏览器而没有退出,也是处于在线状态的,后面人也是无法登录的。

1
http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);

​ 但是还有一个问题,被挤掉的人的session信息仍然存储在SessionRegistry里,需要配置一个监听器,监听到session死亡时将其删除。这里只需要配置一个监听器即可。

​ 这个监听器在监听到session死亡时,会发送事件通知。

1
2
3
4
5
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher(){
return new HttpSessionEventPublisher();
}

​ 默认被挤掉的用户再次访问时,会通过write输出一段话,下面这样:

1
2
3
4
5
6
7
8
9
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event)
throws IOException {
HttpServletResponse response = event.getResponse();
response.getWriter().print(
"This session has been expired (possibly due to multiple concurrent "
+ "logins being attempted as the same user).");
response.flushBuffer();
}

​ 这显然不是我们想要的效果,我么想输出一段json或者重定向到首页这样的操作。那么可以这样配置都可以。下面两种配置方式中选择一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
    //自定义处理器   
http.sessionManagement().maximumSessions(1).expiredSessionStrategy(new SessionInformationExpiredStrategy() {
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
HttpServletResponse response = event.getResponse();
response.setContentType("application/json");
response.getWriter().write("{\"status\":\"200\"}");
}
});

//或者配置一个链接, 将会重定向到此链接
http.sessionManagement().maximumSessions(1).expiredUrl("/home");

​ 会话固定攻击导致的问题

​ 为了防止会话固定攻击,每次登录完成后会改变sessionId。这将导致一个问题,如果在登录状态下,再次调用登录接口,SessionRegistry里会将新登录的sessionId记录下来,但不会删除旧登录的sessionId,因为旧的session只是改Id了,并没有销毁。

解决这个问题可以使用下面的办法。配置会话固定攻击的策略为migrateSession。这样会创建一个新的session,并将旧session里的内容复制进来。这样做会触发session销毁的监听器。

1
2
3
http.sessionManagement().maximumSessions(1)
.and()
.sessionFixation().migrateSession();

springSecurity限制多用户登录
https://www.huangchaoyu.com/1889842632.html
作者
hcy
发布于
2020年7月20日
更新于
2024年8月17日
许可协议