Skip to content

Soora33/sensitive-field-filter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 

Repository files navigation

sensitive-field-filter

🛡️ 一个轻量级的Java字段过滤工具,只需两个注解即可优雅地控制接口返回字段。

A lightweight Java field filtering tool that elegantly controls API response fields with just two annotations.

你是否在写接口的时候,是否因为不想将一些敏感数据返回,又或者某个字段的返回结果根本用不上,从而不得不新写一个实体类来包装数据而烦恼。

现在你可以通过 sensitive-field-filter ,通过配置 2 个注解来完成这个操作!

✨ 特性

  • 🚀 极简使用:仅需通过 @SftFilter 搭配 @SftObjectFilter@SftResponseFilter 即可完成字段过滤
  • 🎯 精确控制:可以精确控制需要过滤的字段和替换值
  • 🔌 开箱即用:支持 Spring Boot 自动配置
  • 🛠 灵活配置:支持对象级别和自定义响应级别的过滤控制
  • 💡 使用简单:无需修改现有代码结构
  • 🎨 优雅处理:基于 Spring AOP,对业务代码无侵入

🎯 适用场景

  • 敏感信息过滤(如:密码、密钥等)
  • 数据字段筛选(如:内部字段过滤)
  • 接口数据裁剪(如:不同场景返回不同字段)

🚀 快速开始

添加依赖

在项目中添加依赖:

<dependency>
    <groupId>io.github.soora33</groupId>
    <artifactId>sft</artifactId>
    <version>1.1.0</version>
</dependency>

配置注解

@SftFilter:配置在实体类上需要过滤的字段

可配置项:

value:过滤后的字段值,默认为 null

public @interface SftFilter {
    String value() default "null";
}

@SftObjectFilter: 配置在方法上,适用于直接返回对象,配置后会对该方法的返回值按照 SftFilter配置的字段进行过滤

可配置项:

entity:方法的返回值类型

preserveField:是否需要保留字段,默认为 true

public @interface SftObjectFilter {
    Class<?> entity();
    boolean preserveField() default true;
}

@SftResponseFilter:配置在方法上,适用于封装格式对象,配置后会对该方法的返回值按照 SftFilter配置的字段进行过滤(默认获取封装对象中 data 中的对象)

可配置项:

entity:方法的返回值类型

key:封装数据体中存储数据的字段名,默认为 data

preserveField:是否需要保留字段,默认为 true

public @interface SftResponseFilter {
    Class<?> entity();
    String key() default "data";
    boolean preserveField() default true;
}

⚠️⚠️⚠️ 注意:如果配置 preserveField 为 false,则会将返回值中的实体类对象转为 LinkedHashMap。因为去除过滤字段的实现方式是通过将非过滤字段加入到 Map 内实现的。如果对业务有影响,请不要使用!!!

🛸开始使用

2.1 在实体类上配置 @SftFilter

public class User {
    private String id;
    @SftFilter // 默认将该字段值设为 null
    private String name;
    @SftFilter(value = "Nah") // 修改默认值为 Nah
    private String email;
}

2.2 使用场景示例

下面四个场景分别会展示四种情况,按顺序分别是:
返回 User 对象,保留过滤字段
返回 User 对象,不保留过滤字段
返回 AjaxResult 封装格式对象,保留过滤字段
返回 AjaxResult 封装格式对象,不保留过滤字段

当然也可以对集合类型进行处理,例如:
返回 List<User> 对象
返回 AjaxResult 对象,封装的数据类型为 List<User>
这里碍于篇幅就不对 List 类型的数据做细致演示,使用方法都一样,如:

@SftObjectFilter(entity = Person.class)
public List<Person> getUserList() {
    Person azki = new Person("1", "azki", "azki@email.com");
    Person nayuta = new Person("2", "nayuta", "nayuta@email.com");
    ArrayList<Person> list = Lists.newArrayList(azki, nayuta);
    return list;
}

@SftResponseFilter(entity = AjaxResult.class)
public AjaxResult getUserList() {
    Person azki = new Person("1", "azki", "azki@email.com");
    Person nayuta = new Person("2", "nayuta", "nayuta@email.com");
    ArrayList<Person> list = Lists.newArrayList(azki, nayuta);
    return AjaxResult.success(list);
}
场景一:直接返回对象的过滤
@SftObjectFilter(entity = User.class)
public User getUserToObj() {
    User user = new User("1", "Azki", "Azki@email.com");
    return user;
}
  • 返回结果: Person(id=1, name=null, email=Nah)
场景二:直接返回对象的过滤(不保留字段)

⚠️ preserveField 设置为 false,会将返回结果转为 Map
⚠️ preserveField 设置为 false 同时使用的是 SftObjectFilter 注解,那么返回值类型必须为 Object!

@SftObjectFilter(entity = Person.class, preserveField = false)
public Object getUserToObj() {
    User user = new User("1", "Azki", "Azki@email.com");
    return user;
}
  • 返回结果: {id=1}

下面场景会使用到封装格式对象,封装格式大致分为两种,第一种是以对象的形式,通过字段存储数据,例如:

public class AjaxResult implements Serializable {
    @Serial
    private static final long serialVersionUID = -7126327333321005351L;
    private String msg;
    private Integer code;
    private Object data;

    // get...set...方法

    private static AjaxResult rest(Object object) {
        AjaxResult ajaxResult = new AjaxResult();
        ajaxResult.setMsg("success");
        ajaxResult.setData(object);
        ajaxResult.setCode(200);
        return ajaxResult;
    }

    public static AjaxResult success(Object object) {
        return rest(object);
    }
}

第二种则是 Map 的形式存储数据,内部通过 put 的方式存储数据,例如:

public class AjaxResultMap extends HashMap<Object,Object> implements Serializable {
    @Serial
    private static final long serialVersionUID = -7127333321005351L;
    private static String msg;
    private Integer code;
    private Object data;


    private AjaxResultMap(Object object) {
        super.put("msg", "success");
        super.put("data", object);
        super.put("code", 200);
    }

    public static AjaxResultMap success(Object object) {
        return new AjaxResultMap(object);
    }
}

无论是哪种方式,SftResponseFilter 内部都对其进行了实现,这里以其中一种演示: 请注意, @SftResponseFilter 注解默认会获取封装格式内的 data 字段或key。 如果你的封装格式存放数据不叫 data,请在注解中的 key 中指定。
例如你的封装格式存放数据叫 body,请在注解中将 key 指定为 body

@SftResponseFilter(entity = AjaxResult.class, key = "body")

场景三:封装格式对象的过滤
@SftResponseFilter(entity = AjaxResult.class)
public AjaxResult getUserToRes() {
    User user = new User("1", "Azki", "Azki@email.com");
    return AjaxResult.success(user);
}
  • 返回结果:
{
  "msg": "success",
  "code": 200,
  "data": {
    "id": "1",
    "name": null,
    "email": "Nah"
  }
}
场景四:封装格式对象的过滤(不保留字段)

⚠️ preserveField 设置为 false,会将返回结果转为 Map

@SftResponseFilter(entity = AjaxResult.class, preserveField = false)
public AjaxResult getUserToRes() {
    User user = new User("1", "Azki", "Azki@email.com");
    return AjaxResult.success(user);
}
  • 返回结果:
{
  "msg": "success",
  "code": 200,
  "data": {
    "id": "1"
  }
}

2.3 其他配置

可以通过 SftConfig 对一些参数进行调整:

严格规则校验:在错误配置的情况下,考虑到程序健全性,可以选择是否将原数据返回。默认为 false

// 开启严格规则校验
SftConfig.setStrictTypeChecking(true);

场景 开启前 开启后
实际返回值类型与 entity 类型不一致 仅打印 error 日志,返回原数据 抛出类型匹配异常
key 对应字段不存在或 key 内数据为 null 仅打印 error 日志,返回原数据 抛出类型匹配异常

📃 常见问题

同类中,主方法内调用被 @SftObjectFilter@SftResponseFilter 修饰的子方法,过滤失效

出现原因:Spring AOP 的代理机制问题,当在一个类中调用另一个被注解修饰的方法,这个注解不会生效。因为 Spring AOP 基于代理实现,而内部调用绕过了代理

解决方案:使用下面方式进行同类调用

public void selectPerson() {
 // this.getUser() -> ((YourClass)AopContext.currentProxy()).getUser().method();
 AjaxResult ajaxResultMap = ((UserController) AopContext.currentProxy()).getPerson();
}

@SftResponseFilter(entity = AjaxResult.class)
public AjaxResult getPerson() {
 Person person = new Person("1","person","person@email.com");
 return AjaxResult.success(person);
}

About

一个轻量级的Java字段过滤工具,只需两个注解即可优雅地控制接口返回字段。

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages