SpringBoot中结合SimplePropertyPreFilter排除JSON敏感属性

在SpringBoot开发中,经常需要从JSON响应中排除敏感属性(如密码、身份证号等),FastJson提供的SimplePropertyPreFilter及其扩展类是实现这一需求的常用方案。以下是详细的实现方法和最佳实践:

1. 基础实现方案

1.1 直接使用SimplePropertyPreFilter

最简单的实现方式是直接在Controller中创建SimplePropertyPreFilter实例并指定要排除的字段:

sql 复制代码
@GetMapping("/user")
public String getUser() {
    User user = new User("张三", "123456", "1828381828225677");
    
    SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
    filter.getExcludes().add("password");
    filter.getExcludes().add("idNo");
    
    return JSON.toJSONString(user, filter);
}

这种方式简单直接,但需要在每个接口重复编写过滤逻辑。

1.2 使用PropertyPreExcludeFilter扩展类

可以创建一个继承自SimplePropertyPreFilter的扩展类,提供更便捷的链式调用:

typescript 复制代码
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter {
    public PropertyPreExcludeFilter addExcludes(String... filters) {
        for (String filter : filters) {
            this.getExcludes().add(filter);
        }
        return this;
    }
}

// 使用示例
@GetMapping("/user")
public String getUser() {
    User user = new User("张三", "123456", "1828381828225677");
    
    PropertyPreExcludeFilter filter = new PropertyPreExcludeFilter()
        .addExcludes("password", "idNo");
    
    return JSON.toJSONString(user, filter);
}

这种方式通过链式调用简化了代码,提高了可读性。

2. 全局配置方案

2.1 配置FastJsonHttpMessageConverter

在SpringBoot中,可以通过配置FastJsonHttpMessageConverter实现全局过滤:

java 复制代码
@Configuration
public class FastJsonConfig {
    
    @Bean
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        FastJsonConfig config = new FastJsonConfig();
        
        // 配置全局过滤器
        PropertyPreExcludeFilter filter = new PropertyPreExcludeFilter()
            .addExcludes("password", "idNo", "creditCard");
        
        config.setSerializeFilters(filter);
        converter.setFastJsonConfig(config);
        return converter;
    }
}

这种配置会对所有使用FastJson序列化的响应生效。

2.2 结合AOP实现动态过滤

对于需要根据不同接口动态过滤不同字段的场景,可以使用AOP:

java 复制代码
@Aspect
@Component
public class SensitiveDataAspect {
    
    @Around("@annotation(com.example.SensitiveData)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        
        SensitiveData sensitiveData = ((MethodSignature) joinPoint.getSignature())
            .getMethod().getAnnotation(SensitiveData.class);
        
        PropertyPreExcludeFilter filter = new PropertyPreExcludeFilter()
            .addExcludes(sensitiveData.excludes());
        
        return JSON.toJSONString(result, filter);
    }
}

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SensitiveData {
    String[] excludes();
}

// 使用示例
@GetMapping("/user")
@SensitiveData(excludes = {"password", "idNo"})
public User getUser() {
    return new User("张三", "123456", "1828381828225677");
}

这种方式提供了最大的灵活性,可以根据不同接口需求定制过滤规则。

3. 高级应用场景

3.1 结合注解实现条件过滤

可以自定义注解实现更智能的过滤,如根据字段值决定是否序列化:

java 复制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomizeJsonExclude {
}

// 自定义过滤器
public class CustomPropertyPreFilter implements PropertyPreFilter {
    @Override
    public boolean apply(JSONSerializer serializer, Object source, String name) {
        try {
            Field field = source.getClass().getDeclaredField(name);
            field.setAccessible(true);
            
            // 检查是否有自定义注解
            if (field.isAnnotationPresent(CustomizeJsonExclude.class)) {
                Object value = field.get(source);
                return value != null; // 值为null时不序列化
            }
            return true;
        } catch (Exception e) {
            return true;
        }
    }
}

// 配置到FastJsonConfig中
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
    FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
    FastJsonConfig config = new FastJsonConfig();
    config.setSerializeFilters(new CustomPropertyPreFilter());
    converter.setFastJsonConfig(config);
    return converter;
}

这种方式类似于Jackson的@JsonInclude注解功能。

3.2 多过滤器组合使用

FastJson支持同时使用多个过滤器:

typescript 复制代码
// 排除敏感字段的过滤器
PropertyPreExcludeFilter sensitiveFilter = new PropertyPreExcludeFilter()
    .addExcludes("password", "idNo");

// 格式化BigDecimal的过滤器
ValueFilter decimalFilter = (object, name, value) -> {
    if (value instanceof BigDecimal) {
        return ((BigDecimal) value).setScale(2, RoundingMode.HALF_UP);
    }
    return value;
};

// 在Controller中使用
@GetMapping("/account")
public String getAccount() {
    Account account = accountService.getCurrentAccount();
    
    return JSON.toJSONString(account, sensitiveFilter, decimalFilter);
}

这种组合方式可以同时处理字段排除和值格式化等需求。

4. 最佳实践建议

  1. 性能考虑:频繁创建过滤器实例会影响性能,建议将常用过滤器配置为单例
  2. 安全基线 :定义项目统一的敏感字段清单,如password, idNo, phone, email
  3. 日志处理:在日志打印时也应使用相同的过滤逻辑,避免敏感信息泄露
  4. 文档维护:在API文档中明确标注哪些字段会被自动过滤
  5. 测试验证:编写测试用例验证过滤逻辑,特别是边界条件如null值、空字符串等

5. 与其他方案的对比

方案 优点 缺点 适用场景
SimplePropertyPreFilter 简单直接,无需配置 代码重复,不够灵活 简单项目或临时方案
全局配置 一次配置,全局生效 不够灵活,所有接口使用相同规则 敏感字段固定的项目
AOP+注解 高度灵活,可定制 实现复杂,需要额外配置 复杂项目,不同接口需要不同规则
Jackson注解 声明式,与SpringBoot集成好 需要切换JSON库 新项目或可接受Jackson的项目

在FastJson生态中,SimplePropertyPreFilter及其扩展类提供了简单有效的敏感字段过滤方案,特别适合已经在使用FastJson的项目。

相关推荐
ZHOUZAIHUI1 小时前
WSL(Ubuntu24.04) 安装PostgreSQL
开发语言·后端·scala
i02082 小时前
SpringBoot 项目配置
java·spring boot·后端
月屯2 小时前
后端go完成文档分享链接功能
开发语言·后端·golang
Franciz小测测2 小时前
Python连接RabbitMQ三大方案全解析
开发语言·后端·ruby
海梨花3 小时前
又是秒杀又是高并发,你的接口真的扛得住吗?
java·后端·jmeter
Livingbody3 小时前
win11上wsl本地安装版本ubuntu25.10
后端
用户8356290780514 小时前
如何在 C# 中自动化生成 PDF 表格
后端·c#
星释4 小时前
Rust 练习册 44:Trait 中的同名函数调用
开发语言·后端·rust
京东零售技术4 小时前
并发丢数据深度剖析:JED的锁机制与事务实战踩坑及解决方案
后端
f***68604 小时前
问题:Flask应用中的用户会话(Session)管理失效
后端·python·flask