- 依赖
org.springframework.boot spring-boot-starter-data-redis org.springframework.session spring-session-data-redis
- 配置redis
spring: redis: host: localhost port: 6379
- 配置security
// 注入
private final FindByIndexNameSessionRepository sessionRepository;
@Bean
public SessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry(sessionRepository);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement() // 开启会话管理
.maximumSessions(1) // 最大同时登陆数
// .and().invalidSessionUrl("invalidSession") // 错误session处理
// 属于SessionManagementFilter重定向
// .expiredUrl("/expired") // 被挤下线的会话过期处理 属于ConcurrentSessionFilter将重定向到expiredUrl
.expiredSessionStrategy( // 过期策略(前后端分离)
event -> {
HttpServletResponse response = event.getResponse();
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
String json =
"{"success":false,"message":"SESSION_INVALID","code":401}";
response.getWriter().println(json);
})
.maxSessionsPreventsLogin(true) // 登陆后禁止再次登陆(不允许二次登陆)
// session 共享
.sessionRegistry(sessionRegistry())
;
}
会话次数限制Bug
如果继承 UserDetails 的实体类没有重写 equals 和 hashCode 方法, 或调用了父类的方法 (super), 但父类没重写, 导致比对失败, 可以无限制登陆.
解决办法出处: https://stackoverflow.com/questions/51916715/concurrent-session-management-not-working-i-have-followed-the-documentation-bu
跨域- 单独: @CrossOrigin(origins=“http://允许的域”) 注解(类、方法)
- 全局: addCrosMapping 重写WebMvcCofingurerComposite#addCorsMapping 方法来实现
- 全局: 过滤器Filter方案



