Spring Security(十一)Spring Session解决集群会话问题
一.简介Spring Security提供的会话并发控制是基于内存实现的,在集群部署时如果想要使用会话并发控制,则必须进行适配。session共享,本质上就是存储容器的变动,但如何得到最优存取结构、如何准确清理过期会话,以及如何整合WebSockwt等无法回避。Spring Session就是专门用于解决集群会话问题的,它不仅为集群会话提供了非常完善的支持,与Spring Security的...
·
一.简介
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信息
相关代码:https://github.com/o99o/SpringSecurity/tree/master/SpringSecurity_10_Cluster_Session
更多推荐
已为社区贡献2条内容
所有评论(0)