作为一个稀有的Java妹子,所写的所有博客都只是当作自己的笔记,留下证据自己之前是有用心学习的~哈哈哈哈(如果有不对的地方,也请大家指出,不要悄悄咪咪的不告诉我)
一、前言
在工作中遇到多系统时,比如oa人事相关的是独立的系统,在其他系统登录后,在这个系统不应该再让用户重新登录,想实现一次登录,多系统session共享,有很多种实现方式,针对web业务可以使用springsession,如果是移动端业务可以使用jwt的token,今天主要记录spring session。
二、jar包准备
在此之前已经整合好springboot和spring security,且已经实现了spring security的登录功能,在这基础上实现session共享。
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
如果项目中有用到redis,引入过redis的包就不用重复引入redis的包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
三、配置类
1、redis的配置类,如果项目有就不需要引入
@Configuration
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {
/**
* RedisTemplate配置
*
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
//定义value的序列化方式
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
2、Springsession配置类
@Configuration
public class WebSessionConfiguration extends RedisHttpSessionConfiguration {
public static String redisNamespace = "/supervision";
@Value("${spring.session.redis.timeout:14400}")
private int maxInactiveIntervalInSeconds;
@Value("${spring.session.redis.flushMode:immediate}")
private String flushMode;
/**
* 兼容1.X session的前缀,由于序列化问题,放弃兼容,改为其他方案、
*/
static final String DEFAULT_SPRING_SESSION_REDIS_PREFIX = "spring:session:";
@Bean
public RedisIndexedSessionRepository sessionRepository() {
RedisIndexedSessionRepository repository = super.sessionRepository();
repository.setFlushMode(FlushMode.IMMEDIATE);
repository.setDefaultMaxInactiveInterval(maxInactiveIntervalInSeconds);
repository.setRedisKeyNamespace(DEFAULT_SPRING_SESSION_REDIS_PREFIX + redisNamespace);
return repository;
}
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setUseBase64Encoding(false);
return cookieSerializer;
}
}
配置完成后,就可以直接使用,不需要再写其他代码了,在一个系统登录后,就可以直接访问另外一个系统,不需要再次登录。以下几点是我在使用过程中遇到的需要注意的点:
注意
1、springsecurity中继承User的类需要单独打成jar,在各个系统中引入,因为springsession在缓存session的时候,是以sessionId为key,value里存了class的全路径名,如果包名不一致的话会报类转换出错
java.lang.ClassCastException: com.nmpa.risk.entity.AuthUserDetail cannot be cast to com.security.demo.configuration.web.AuthUserDetail
2、跨域问题,sessionId的生成是在同一个域名下保证生成一个,如果两个系统的域名不一样,session是无法共享的,可以使用nginx进行转发解决。
四、源码解析
我是参考的另一篇文章的,主要就是使用了SessionRepositoryFilter过滤器,所有请求都经过这个过滤器,在这个过滤器中重写了getSession的方法,会去redis里取。原文链接:https://www.cnblogs.com/54chensongxia/p/12096493.html