springboot 之 接口数据脱敏
实际开发中,可能会遇到需要将接口返回数据进行脱敏,这里记录下如何操作。
这里默认使用的是springboot自带的Jackson库
定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive {/*** 脱敏策略*/SensitiveStrategy strategy();
}
定义脱敏策略
/*** 脱敏策略,枚举类,针对不同的数据定制特定的策略*/
public enum SensitiveStrategy {/*** 用户名*/USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),/*** 身份证*/ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),/*** 手机号*/PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),/*** 地址*/ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****"));private final Function<String, String> desensitizer;SensitiveStrategy(Function<String, String> desensitizer) {this.desensitizer = desensitizer;}public Function<String, String> desensitizer() {return desensitizer;}
}
应用策略到类属性
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {private SensitiveStrategy strategy;@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {gen.writeString(strategy.desensitizer().apply(value));}/*** 获取属性上的注解属性*/@Overridepublic JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {Sensitive annotation = property.getAnnotation(Sensitive.class);if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {this.strategy = annotation.strategy();return this;}return prov.findValueSerializer(property.getType(), property);}
}
定义测试类
@Data
public class Person {/*** 真实姓名*/@Sensitive(strategy = SensitiveStrategy.USERNAME)private String userName;/*** 地址*/@Sensitive(strategy = SensitiveStrategy.ADDRESS)private String address;/*** 电话号码*/@Sensitive(strategy = SensitiveStrategy.PHONE)private String phoneNumber;/*** 身份证号码*/@Sensitive(strategy = SensitiveStrategy.ID_CARD)private String idCard;
}
定义测试接口
@GetMapping("test/sensitiveData")
public Person test(){Person user = new Person();user.setUserName("小明");user.setPhoneNumber("123456789");user.setAddress("中国辽宁省葫芦岛");user.setIdCard("52462545262256562");return user;
}
测试结果
http://localhost:8001/test/sensitiveData
实际使用中,可以根据自己的业务适度调整,这里只是实现了在Jackson序列化时的处理。