Spring Boot Security Redis共享会话登录失败问题求助
解决Spring Boot Security + Redis共享会话登录失败问题
我之前也碰到过几乎一模一样的Redis共享会话序列化问题,核心原因就是SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper这个内部类没有实现Serializable接口,而默认的JDK序列化器无法处理它。给你几个经过验证的解决方案:
方案一:使用Jackson序列化器处理Security上下文
Spring Security提供了专门的Jackson模块来支持自身类的序列化,搭配Jackson2JsonRedisSerializer可以完美解决大部分序列化问题,步骤如下:
- 配置自定义的Redis序列化器,引入Security的Jackson模块:
@Configuration public class RedisSessionConfig { @Bean public RedisSerializer<Object> springSessionDefaultRedisSerializer() { Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper objectMapper = new ObjectMapper(); // 注册Spring Security的Jackson模块,处理Security相关类的序列化 objectMapper.registerModule(new SecurityJackson2Modules()); // 配置Jackson支持所有属性访问,启用默认类型以处理多态 objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(objectMapper); return serializer; } }
- 确保你的Spring Boot依赖使用starter管理版本,避免版本冲突:
<!-- pom.xml --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
方案二:自定义SecurityContextRepository过滤不可序列化对象
如果不想修改Redis序列化器,也可以通过自定义HttpSessionSecurityContextRepository,在存储Security上下文时移除不可序列化的引用:
@Component public class SerializableSecurityContextRepository extends HttpSessionSecurityContextRepository { @Override protected void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) { // 创建一个仅包含可序列化内容的SecurityContext副本 SecurityContext serializableContext = new SecurityContextImpl(); serializableContext.setAuthentication(context.getAuthentication()); // 只存储纯净的SecurityContext,避免携带HttpSessionWrapper等不可序列化对象 super.saveContext(serializableContext, request, response); } }
然后在Security配置中指定使用这个自定义Repository:
@Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private SerializableSecurityContextRepository securityContextRepository; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .securityContext(config -> config .securityContextRepository(securityContextRepository) ) .formLogin(form -> form.permitAll()) .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()); return http.build(); } }
方案三:检查版本兼容性
确保Spring Boot、Spring Security和Spring Session的版本完全兼容,建议直接使用Spring Boot的starter依赖,它会自动管理所有相关组件的版本,避免因版本不匹配导致的序列化异常。
补充排查点
- 查看完整错误日志,确认是否抛出
NotSerializableException,如果是,那基本就是这个内部类无法序列化的问题; - 检查Redis中存储的
SPRING_SECURITY_CONTEXT键值,确认是否包含HttpSessionWrapper的引用;
内容的提问来源于stack exchange,提问作者Zhen
相关产品推荐
相关产品推荐

