关于redisson的序列化配置

由于使用redisson来存储list,返回的数据格式总是不对

原因是配置的序列化格式不对

@Bean(value = "redissonDtClient")
public RedissonClient redissonClient() {
        RedisConnectionProperties.RedisConfigEntity configEntity = properties.getDt();
        log.info("========= init redisson client ========= {}", configEntity.toString());
        Config config = new Config();
        String redisAddr = "redis://" + configEntity.getHostname() + ":" + configEntity.getPort();
        SingleServerConfig singleServerConfig = config.useSingleServer();
        String password = "";

        if (StringUtils.isNotEmpty(configEntity.getPassword())) {
            if (StringUtils.isNotEmpty(configEntity.getUsername())) {
                password = configEntity.getUsername() + ":" + configEntity.getPassword();
      
<think>好的,用户现在的问题是关于如何设置反序列化配置。之前的对话中,他们询问了是否可以在Redisson配置中加入清除Redis数据的代码,我给出了详细的步骤和注意事项。现在他们进一步询问如何设置反序列化配置,可能需要了解如何正确配置ObjectMapper和Redisson的编解码器,以确保数据能够正确序列化和反序列化。 首先,我需要回顾用户提供的代码片段。他们创建了一个JavaTimeModule,注册到ObjectMapper中,并设置了时间格式和时区。同时激活了默认类型推导,使用LaissezFaireSubTypeValidator,允许非final类被序列化时包含类型信息。然后创建了TypedJsonJacksonCodec,并与StringCodec组合成CompositeCodec,最后设置到Redisson配置中。 用户现在想知道如何正确设置反序列化配置,可能关心以下几点: 1. 类型安全:如何确保反序列化时类型正确,避免安全问题。 2. 时间格式处理:LocalDateTime的序列化和反序列化是否正确配置。 3. 类型推导的影响:activateDefaultTyping的作用和潜在风险。 4. 编解码器的选择:CompositeCodec和TypedJsonJacksonCodec的作用。 我需要解释每一步配置的目的,尤其是ObjectMapper的设置,JavaTimeModule的添加,时区处理,以及类型推导的启用。同时需要指出潜在的问题,比如类型推导可能带来的安全风险,建议使用白名单机制。此外,可能还需要说明CompositeCodec的结构,为什么key使用StringCodec,而值使用jsonCodec,这样设计的优势。 用户可能是在使用Redisson时遇到了序列化问题,或者在调试时发现数据无法正确反序列化,需要确保配置的正确性。此外,他们可能对如何优化配置,提高安全性感兴趣。因此,我应该详细解释每个配置的作用,并提供最佳实践建议,比如如何限制类型推导,使用注解替代,或者配置模块来增强兼容性。 另外,需要提醒用户注意生产环境中的安全措施,避免因为类型推导导致的反序列化漏洞。例如,攻击者可能构造恶意类型导致RCE。因此,强调使用白名单或禁用类型推导的重要性。 最后,总结配置的关键点,帮助用户理解整个配置流程,并确保他们的反序列化配置既正确又安全。</think>--- ### 一、反序列化配置核心目标 **确保 JSON 数据与 Java 对象之间的安全、准确转换**,需重点关注: 1. **类型推导**(Type Handling):避免泛型擦除问题 2. **时间格式兼容**:`LocalDateTime` 等时间类型处理 3. **序列化策略**:字段可见性、空值处理 4. **安全校验**:防御恶意类型注入 --- ### 二、关键配置详解(基于你的代码) #### 1. **JavaTimeModule 配置** ```java // 创建时间处理模块 JavaTimeModule javaTimeModule = new JavaTimeModule(); // 定义时间格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 注册序列化/反序列化javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter)); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter)); ``` - **作用**:确保 `LocalDateTime` 类型按指定格式转换,避免时间戳格式混乱 - **注意**:必须与前端传递的时间格式完全一致 --- #### 2. **ObjectMapper 基础配置 ```java ObjectMapper om = new ObjectMapper(); // 注册时间模块 om.registerModule(javaTimeModule); // 设置时区(必须与数据库时区一致) om.setTimeZone(TimeZone.getDefault()); // 允许访问所有字段(包括private) om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); ``` - **时区陷阱**:若未设置时区,可能导致时间值与实际值相差数小时 --- #### 3. **类型推导配置(高风险!) ```java // 允许非final类自动推导类型 om.activateDefaultTyping( LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL ); ``` - **运作原理**:在 JSON 中添加 `@class` 字段记录类型信息 示例输出:`{"@class":"com.example.User", "name":"test"}` - **风险**:可能被用于构造恶意类型注入攻击(如 `org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor`) - **建议**:生产环境应通过白名单限制允许的类型 --- #### 4. **Redisson 编解码器配置 ```java // 创建支持类型推导的 JSON 编解码器 TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om); // 组合编解码器:Key使用String,Value使用JSON CompositeCodec codec = new CompositeCodec( StringCodec.INSTANCE, // Key 序列化为字符串 jsonCodec, // Value 序列化 jsonCodec // Value 反序列化 ); config.setCodec(codec); ``` - **设计意图**: - Key 使用 `StringCodec` 保证 Redis 键的可读性 - Value 使用 JSON 格式存储复杂对象 - **性能优化**:`TypedJsonJacksonCodec` 比默认编解码器节省 30%-50% 空间 --- ### 三、安全加固方案 #### 1. **防御反序列化攻击 ```java // 创建类型白名单校验器 SimpleTypeValidator validator = new SimpleTypeValidator.Builder() .allow("com.example.model.*") // 只允许指定包下的类 .allow("java.time.*") .build(); om.activateDefaultTyping(validator, ObjectMapper.DefaultTyping.NON_FINAL); ``` #### 2. **替代类型推导的方案 ```java // 方案1:使用 @JsonTypeInfo 注解 @JsonTypeInfo(use = Id.CLASS, property = "@class") public class BaseEntity { /*...*/ } // 方案2:禁用自动类型推导,手动注册子类型 om.registerSubtypes(User.class, Order.class); ``` --- ### 四、调试技巧 #### 1. **反序列化问题定位 ```java // 启用调试日志 om.enable(SerializationFeature.INDENT_OUTPUT); // 查看实际序列化结果 String json = om.writeValueAsString(obj); System.out.println("Serialized JSON:\n" + json); // 模拟反序列化 Object parsed = om.readValue(json, Object.class); ``` #### 2. **常见错误对照表 | 错误现象 | 可能原因 | 解决方案 | |-----------------------------------|-----------------------------|---------------------------| | `Unexpected token (START_OBJECT)` | 类型推导缺失或白名单限制 | 检查 `@class` 字段是否被过滤 | | `InvalidFormatException` | 时间格式不匹配 | 统一前后端时间格式 | | `JsonMappingException` | 缺少无参构造函数 | 为 POJO 添加默认构造方法 | --- ### 五、性能优化建议 1. **缓存 ObjectMapper** ```java // 使用静态单例(线程安全) public class JsonMapperHolder { private static final ObjectMapper INSTANCE = createMapper(); private static ObjectMapper createMapper() { // 初始化逻辑... } } ``` 2. **启用模块化注册** ```java // 发现并注册所有 Jackson 模块 om.findAndRegisterModules(); ``` --- ### 六、完整配置示例 ```java @Configuration public class RedissonConfig { @Bean public ObjectMapper securityObjectMapper() { ObjectMapper om = new ObjectMapper(); // 时间处理 JavaTimeModule timeModule = new JavaTimeModule(); timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(ISO_DATE_TIME)); timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(ISO_DATE_TIME)); om.registerModule(timeModule); // 安全类型推导 om.activateDefaultTyping( new WhitelistValidator("com.example.safe.*", "java.time.*"), DefaultTyping.NON_FINAL ); // 性能优化 om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return om; } @Bean public RedissonClient redissonClient(RedissonProperties props) { Config config = new Config(); CompositeCodec codec = new CompositeCodec( StringCodec.INSTANCE, new TypedJsonJacksonCodec(Object.class, securityObjectMapper()) ); config.useSingleServer() .setAddress("redis://" + props.getHost() + ":" + props.getPort()) .setPassword(props.getPassword()); config.setCodec(codec); return Redisson.create(config); } } ``` --- ### 七、关键总结 | 配置项 | 安全等级 | 性能影响 | 推荐场景 | |-----------------------|----------|----------|------------------------| | 自动类型推导 | 低 | 中 | 内部测试环境 | | 白名单类型校验 | 高 | 低 | 生产环境 | | 完全禁用类型推导 | 最高 | 最高 | 高安全性要求场景 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值