Spring Boot 如何使用两个不同的serialVersionUID处理Redis安全上下文序列化

5kgi1eie  于 2023-03-18  发布在  Spring
关注(0)|答案(1)|浏览(189)

我是共享Redis会话的两个不同的服务(服务A和服务B),两个服务都使用Spring-boot 1.5
服务A是身份验证服务(SSO),而服务B是用户服务
最近,服务B升级到了Spring-boot 2.7。
在这两个服务之间共享会话Id已经成为一个问题。
我们不想升级服务A(至少现在不想),因为其他服务依赖于它。
如何在不升级服务A的情况下处理Session序列化。
我尝试过为Redis定制序列化,但失败了。

@Configuration
public class RedisConfig {

    @Autowired
    @Qualifier("springSessionDefaultRedisSerializer")
    private RedisSerializer<Object> serializer;
    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("redis", 6379);
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

@Configuration
@Slf4j
public class SpringSessionConfig implements BeanClassLoaderAware {

    private ClassLoader loader;


    @Bean("springSessionDefaultRedisSerializer")
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer(objectMapper());
    }

    /**
     * Customized {@link ObjectMapper} to add mix-in for class that doesn't have default constructors
     *
     * @return the {@link ObjectMapper} to use
     */
    private ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//        mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));
        return mapper;
    }

    /*
     * @see
     * org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang
     * .ClassLoader)
     */
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.loader = classLoader;
    }
}
7vhp5slm

7vhp5slm1#

使用java反射,我可以将不同的serialVersionUID设置为相同的值。错误已经消失,但是身份验证不成功。

@PropertySource("classpath:application.yml")
@EnableRedisHttpSession
@SpringBootApplication
public class SingleSignOnApplication extends SpringBootServletInitializer {

    @Value("${spring.session.timeout}")
    private Integer maxInactiveInterval;

    @Bean
    public RedisOperationsSessionRepository sessionRepository(RedisConnectionFactory factory) {
        RedisOperationsSessionRepository sessionRepository =
            new RedisOperationsSessionRepository(factory);
        sessionRepository.setDefaultMaxInactiveInterval(maxInactiveInterval);
        return sessionRepository;
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SingleSignOnApplication.class);
    }

    public static void main(String[] args) throws Exception {
        updateSerialVersionUID(SecurityContextImpl.class);
        updateSerialVersionUID(UsernamePasswordAuthenticationToken.class);
        updateSerialVersionUID(SimpleGrantedAuthority.class);
        updateSerialVersionUID(WebAuthenticationDetails.class);
        updateSerialVersionUID(LdapUserDetailsImpl.class);
        updateSerialVersionUID(AnonymousAuthenticationToken.class);
        SpringApplication.run(SingleSignOnApplication.class, args);
    }

    private static void updateSerialVersionUID(Class<?> clazzToCustomize) throws  Exception {
        Field staticFinalFieldToReplace = clazzToCustomize.getDeclaredField("serialVersionUID");
        setFinalStatic(staticFinalFieldToReplace, 570L);
    }
    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        AccessController.doPrivileged((PrivilegedAction) () -> {
            modifiersField.setAccessible(true);
            return  null;
        } );
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }
}

相关问题