读《SpringSecurity实战(陈木鑫)》
陈木鑫老师阐述的观点是,解决集群会话的常见方案有三种:
1.session保持
2.session复制
3.session共享
session保持也叫粘滞会话
书中说,通常采用IP哈希负载策略将来自相同客户端的请求转发至相同的服务器进行处理。
session复制
是指在集群服务器之间同步session数据,已达到各个实例之间会话状态一致的做法。
session共享
是指将session从服务器内存抽离出来,集中存储到独立的数据容器,并由各个服务器共享。
<!--spring session核心依赖-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</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>
package com.zcw.demospringsecurity.demo11;
import org.springframework.beans.factory.annotation.Autowired;
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.FindByIndexNameSessionRepository;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
import javax.swing.*;
/**
* @ClassName : HttpSessionConfig
* @Description :启用基于Redis的HttpSession实现
* @Author : Zhaocunwei
* @Date: 2020-04-12 13:56
*/
@EnableRedisHttpSession
public class HttpSessionConfig {
@Bean
public RedisConnectionFactory connectionFactory(){
return new JedisConnectionFactory();
}
@Autowired
private FindByIndexNameSessionRepository sessionRepository;
/**
* SpringSessionBackedSessionRegistry是session为Spring Security
* 提供的用于集群环境下控制会话并发的会话注册表实现类
*/
@Bean
public SpringSessionBackedSessionRegistry sessionBackedSessionRegistry(){
return new SpringSessionBackedSessionRegistry(sessionRepository);
}
//httpSession的事件监听,改用session提供的会话注册表
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher(){
return new HttpSessionEventPublisher();
}
}
package com.zcw.demospringsecurity.demo11;
import org.springframework.beans.factory.annotation.Autowired;
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.security.SpringSessionBackedSessionRegistry;
/**
* @ClassName : WebSecurityConfig
* @Description :
* @Author : Zhaocunwei
* @Date: 2020-04-12 15:29
*/
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SpringSessionBackedSessionRegistry redisSessionRegistry;
@Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/admin/**")
.hasAuthority("ROLE_ADMIN")
.antMatchers("/user/**")
.hasRole("USER")
.antMatchers("/app/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf()
.disable()
.formLogin()
.and()
.sessionManagement()
.maximumSessions(1)
//使用session提供的会话注册表
.sessionRegistry(redisSessionRegistry);
}
}