14 spring-security 中的 SessionManagerFilter 导致的每刷新一次页面 JSESSIONID 切换一次 导致 session 不可用

前言

这个问题是最近的一个老项目 碰到的一个问题

假设 我现在在同一个页面, 刷新一下页面, 加载完毕之后, 再刷新一下页面 

然后 可以看到的是两次刷新页面所发送的请求, 携带的 JSESSIONID 不一样, 然后 导致了 服务端这边使用 session 相关特性失效 

然后 这里我们就是来看一下 处理的原因  

首先项目是引入了 spring-security, 然后 进而导致的这个问题

情况如下, 以红线作为 第一次 和 第二次 相关网络请求的分隔符

然后可以看到的是 第一批次的请求中携带的 JSESSIONID 均为 “4415237FB3237945BB3103BCB187F5F3”

然后 响应了一个 set-cookie 的响应头, 告诉客户端这边重新更新 cookie, 第一批次的请求的所有响应里面都有这个 set-cookie, 并且每一个 set-cookie 中的 JSESSIONID 不一

第二个批次的请求如下, 可以看到携带的 JSESSIONID 为 “9142F6629C4D076207C283CD8A103BC9”

然后 客户端这边挑选的是 上面的 ”/serviceStatsByLv2” 的 JSESSIONID 进行设置, 当然 这个挑选是由浏览器这边来控制的, 我们暂时不关心这个问题 

然后第二批次的这批请求, 基本上都有 set-cookie 的响应头 

按照 我们的通常的 web 经验的理解, 一个 session 应该是有一定的生命周期的, 为啥这里每一批次请求 就会切换 JSESSIONID 呢??

这是和 spring-security 中的一个 SessionManagementFilter 有关系 

Spring MVC 5.2 版本整合 Spring Session with Redis 2.2 主要是为了在分布式环境中利用缓存技术来管理和同步用户的会话数据,使得应用程序可以在多个节点上同时提供服务。下面是基本步骤: 1. 添加依赖:在你的 Maven 或 Gradle 项目中添加以下依赖: ```xml <!-- Maven --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>2.2.x</version> </dependency> <!-- Gradle --> implementation 'org.springframework.session:spring-session-data-redis:2.2.x' ``` 2. 配置 Redis:在 `application.properties` 或 `application.yml` 中配置 Redis 连接信息: ```properties spring.redis.host=localhost spring.redis.port=6379 spring.redis.password=<your_redis_password> ``` 3. 创建 RedisTemplate:创建并配置 RedisTemplate,用于操作 Redis 数据库。 ```java @Bean public RedisTemplate<String, HttpSession> sessionRedisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, HttpSession> template = new RedisOperationsSessionRepository<>(factory); Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jsonSerializer.setObjectMapper(om); template.setValueSerializer(jsonSerializer); template.setKeySerializer(new StringRedisSerializer()); return template; } ``` 4. 配置 Spring Session:在 Spring 容器中开启 session 管理。 ```java @Configuration @EnableWebMvc @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private HttpSessionEventPublisher publisher; @Bean public HttpSessionStrategy httpSessionStrategy() { return new DefaultSavedRequestAwareSessionStrategy(); } @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .formLogin() .disable() .and() .logout() .logoutSuccessUrl("/") .deleteCookies("JSESSIONID") .invalidateHttpSession(true); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 如果有需要,可以在此处配置认证机制 } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { SimpleCacheManager manager = new SimpleCacheManager(); manager.setCacheNames(Arrays.asList("sessions")); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(15)) .serializeKeysWith(RedisSerializationSupport.STRING) .serializeValuesWith(jsonSerializer); manager.setCacheDefaults(config); return manager; } } ``` 5. 启用 Spring Session 支持:在 `WebMvcConfigurer` 接口中配置 session 存储: ```java @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // 如果你想支持序列化/反序列化 JSON,这里添加一个 Jackson2JsonHttpMessageConverter } } ``` 完成上述步骤后,Spring MVC 5.2 就已经整合了 Spring Session with Redis 2.2,会话数据会被存储在 Redis 中,提供分布式场景下的会话管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值