You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SecurityJackson2Modules序列化Spring Security会话时BigDecimal兼容问题如何解决

解决方案

你现有的方案对业务代码侵入性较强,每个用到BigDecimal的字段都需要手动加Jackson注解,维护成本高,更合理的方案是全局修改Spring Session的Redis序列化配置,有两种常用实现路径:

方案1:全局扩展ObjectMapper配置,业务代码无侵入

直接在Spring Session配置类中自定义Redis序列化用的ObjectMapper,显式支持BigDecimal序列化,不需要修改任何业务DTO代码,代码如下:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession
public class SpringSessionRedisConfig {

    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        ObjectMapper mapper = new ObjectMapper();
        // 注册Spring Security内置的Jackson序列化模块,保证Security相关对象正常序列化
        mapper.registerModules(SecurityJackson2Modules.getModules(this.getClass().getClassLoader()));
        // 配置多态序列化规则,显式允许包括BigDecimal在内的非final类型的序列化
        mapper.activateDefaultTyping(
            LaissezFaireSubTypeValidator.instance,
            ObjectMapper.DefaultTyping.NON_FINAL
        );
        return new GenericJackson2JsonRedisSerializer(mapper);
    }
}

如果对反序列化安全要求较高,可以替换LaissezFaireSubTypeValidator为自定义的子类,只放行业务包下的DTO类和java.math.BigDecimal这类需要的JDK类型,避免反序列化漏洞。

方案2:自定义BigDecimal序列化规则,避免冗余类型信息

如果不想让序列化结果增加多余的多态类型字段,也可以单独注册BigDecimal的序列化/反序列化器,代码如下:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.math.BigDecimal;

// 自定义序列化器
class CustomBigDecimalSerializer extends StdSerializer<BigDecimal> {
    public CustomBigDecimalSerializer() {
        super(BigDecimal.class);
    }

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(value.toString());
    }
}

// 自定义反序列化器
class CustomBigDecimalDeserializer extends StdDeserializer<BigDecimal> {
    public CustomBigDecimalDeserializer() {
        super(BigDecimal.class);
    }

    @Override
    public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return new BigDecimal(p.getValueAsString());
    }
}

然后在方案1的ObjectMapper配置中注册该模块即可:

SimpleModule bigDecimalModule = new SimpleModule();
bigDecimalModule.addSerializer(BigDecimal.class, new CustomBigDecimalSerializer());
bigDecimalModule.addDeserializer(BigDecimal.class, new CustomBigDecimalDeserializer());
mapper.registerModule(bigDecimalModule);

这种方案序列化后的结果不会包含多余的类型字段,存储空间更小,且不需要修改业务代码。

内容的提问来源于stack exchange,提问作者Alexey Usharovski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:45:00