一.简介

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

二.实战

1.在pom.xml引入依赖

<!-- Spring Session 依赖-->
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session</artifactId>
		</dependency>
		<!-- Spring session 对接Redis的必要依赖-->
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-data-redis</artifactId>
		</dependency>
		<!-- spring boot 整合Redis核心依赖-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
		</dependency>

2.配置Spring Session


package com.zit.springsecurity.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * 为Spring Security提供集群支持的会话注册表
 */
@EnableRedisHttpSession
public class HttpSessionConfig {

    // 提供Redis连接,默认是localhost:6379
    @Bean
    public RedisConnectionFactory connectionFactory(){
        return new JedisConnectionFactory();
    }

    // httpSession的事件监听,改用session提供的会话注册表
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher(){
        return new HttpSessionEventPublisher();
    }
}

3.WebSecurity配置

package com.zit.springsecurity.configuration;

import com.zit.springsecurity.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    private MyUserDetailsService myUserDetailsService;

    //RedisOperationsSessionRepository
    @Autowired
    private FindByIndexNameSessionRepository mySessionRepository;

    // 是session为Spring Security提供的
    // 用于在集群环境下控制会话并发的会话注册表实现
    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry(){
        return new SpringSessionBackedSessionRegistry(mySessionRepository);
    }

    // 将新的会话注册表提供给Spring Security
    @Autowired
    private SpringSessionBackedSessionRegistry redisSessionRegistry;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(myUserDetailsService).passwordEncoder(new MyPasswordEncoder());
    }

    @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()
                .formLogin()
                .and()
                .sessionManagement()
                // 最大会话数设置
                .maximumSessions(1)
                // 阻止新会话登录
                .maxSessionsPreventsLogin(true)
                // 使用session提供的会话注册表
                .sessionRegistry(redisSessionRegistry);
    }
}

4.Redis中Session信息
Redis中Session信息

相关代码:https://github.com/o99o/SpringSecurity/tree/master/SpringSecurity_10_Cluster_Session

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐