Spring WebFlux Security实现单用户单会话的等效方案咨询
WebFlux Security 单用户单有效会话实现方案
实现思路
Spring WebFlux Security 官方提供了响应式场景下的并发会话管控组件,无需适配非响应式的SessionAuthenticationStrategy相关API,直接使用ReactiveSessionRegistry和ConcurrentSessionControlWebFilter即可对齐非响应式框架的配置效果。
完整配置代码
1. 注册响应式会话注册表
@Bean public ReactiveSessionRegistry reactiveSessionRegistry() { // 内存实现,分布式场景可自行扩展Redis版本的实现 return new InMemoryReactiveSessionRegistry(); }
2. 配置并发会话管控过滤器
@Bean public WebFilter concurrentSessionControlWebFilter(ReactiveSessionRegistry reactiveSessionRegistry) { ConcurrentSessionControlWebFilter filter = new ConcurrentSessionControlWebFilter(reactiveSessionRegistry); // 限制单用户最大会话数为1 filter.setMaximumSessions(1); // 会话数超出限制时,直接失效最早的会话,不抛出异常,和你原非响应式配置逻辑一致 filter.setExceptionIfMaximumExceeded(false); // 可选:自定义旧会话失效后的返回提示 // filter.setInvalidSessionStrategy((exchange, invalidSessionException) -> { // exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); // DataBuffer buffer = exchange.getResponse().bufferFactory() // .wrap("您的账号已在其他设备登录,当前会话已失效".getBytes(StandardCharsets.UTF_8)); // return exchange.getResponse().writeWith(Mono.just(buffer)); // }); return filter; }
3. 把过滤器加入安全链路
@Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http, WebFilter concurrentSessionControlWebFilter, ReactiveSessionRegistry reactiveSessionRegistry) { return http .authorizeExchange(exchange -> exchange .anyExchange().authenticated() ) // 按需配置登录方式,此处用表单登录做示例 .formLogin(Customizer.withDefaults()) // 注意要把并发会话过滤器加在认证过滤器之前 .addFilterBefore(concurrentSessionControlWebFilter, SecurityWebFiltersOrder.AUTHENTICATION) // 绑定会话注册表到会话管理配置 .sessionManagement(session -> session .sessionRegistry(reactiveSessionRegistry) ) .build(); }
特殊场景说明
如果你使用的是JWT等无状态认证方案,不依赖WebSession,上述配置不生效,需要自行维护用户的有效token白名单:
- 用户登录成功后,将新生成的token存入白名单,同时删除该用户对应的旧token
- 每次请求校验token时,先判断token是否在白名单内,不在则直接拒绝访问
内容的提问来源于stack exchange,提问作者user1578872
相关产品推荐
相关产品推荐

