【Spring Security系列】Spring Security整合Spring Session解决集群会话问题

    技术2022-07-13  66

    Spring Security提供的会话并发控制是基于内存实现的,在集群部署时如果想要使用会话并发控制,则必须进行适配。 session共享,本质上就是存储容器的变动,但如何得到最优存取结构、如何准确清理过期会话,以及如何整合WebSocket等无法回避。Spring Session就是专门用于解决集群会话问题的,它不仅为集群会话提供了非常完善的支持,与Spring Security的整合也有专门的实现。 Spring Session支持多种类型的存储容器,包括Redis、MongoDB等。由于接下来的整合都是基于Redis的,所以大家可以自行准备Redis测试环境,具体如何安装不再赘述。

    在pom.xml中引入三个依赖

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-core</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>

    之后就可以配置Spring Session了,主要是为Spring Security提供集群支持的会话注册表。

    /** * 启用基于redis的HttpSession实现 */ @EnableRedisHttpSession public class HttpSessionConfig { @Autowired private FindByIndexNameSessionRepository sessionRepository; /** * 提供redis连接 */ @Bean public RedisConnectionFactory redisConnectionFactory() { return new JedisConnectionFactory(); } /** * SpringSessionBackedSessionRegistry是session为Spring Security提供的 * 用于在集群环境下控制会话并发的会话注册表实现类 */ @Bean public SpringSessionBackedSessionRegistry sessionRegistry() { return new SpringSessionBackedSessionRegistry(sessionRepository); } /** * httpSession的会话监听, */ @Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); } }

    最后将新的会话注册表提供给Spring Security即可。

    @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SpringSessionBackedSessionRegistry sessionRegistry; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/api/**").hasRole("ADMIN") .antMatchers("/user/api/**").hasRole("USER") .antMatchers("/app/api/**").permitAll() .anyRequest().authenticated() .and() .csrf().disable() .formLogin() .and() .sessionManagement() .maximumSessions(1) // 使用session提供的会话注册表 .sessionRegistry(sessionRegistry); } }

    Spring Session与Spring Security的整合非常简单,如果要验证是否生效,则可以在不同端口上启动多个实例,并在各自端口实例上登录同个账号。若出现挤占,则代表配置生效。登录成功之后,Redis会存储用户session相关的数据,默认命名为spring:session。

                                                                 
    Processed: 0.015, SQL: 9