当前位置:网站首页>It's too strong. An annotation handles the data desensitization returned by the interface
It's too strong. An annotation handles the data desensitization returned by the interface
2022-07-27 03:20:00 【Fat technology house】
Ideas
Code
1. Custom data annotation , Data desensitization strategy can be configured
2. Customize Serializer, Reference resources jackson Of StringSerializer, The following example is only for String Type for desensitization
3. Customize AnnotationIntrospector, Adapt our custom annotation to return the corresponding Serializer
4. Cover ObjectMapper
5. Return the object and annotate it
A pleasant afternoon , Suddenly miss product came up to me , Interrupt my short fishing time, Try to have in-depth communication with me , It's good that I was on guard , Open Rui star Order page of , Hint that there is no one coffee Unsolvable needs , Requirements are information returned by some interfaces , Sensitive data must be desensitized , I thought the other way , Indicate a problem , Make arrangements now .

Ideas
1. It is necessary to make desensitization operation with configurable multiple strategies , Otherwise, desensitize the interfaces one by one , Too much repetitive work , It's obviously against “ I'll lose if I write one more line ” Programmer specification for , reasoning , Define the interface between data desensitization annotation and data desensitization logic , On the return class , Add... To the attributes that need desensitization , And specify the corresponding desensitization policy operation .
2. Next, I just need to intercept the data returned by the controller , Find the attribute operation with desensitization annotation , At first, I planned to use @ControllerAdvice To achieve , However, it is found that you need to reflect the class to get annotations , When the return object is complex , Recursive de reflection is required , Performance will degrade all at once , So change your mind , I think of the usual @JsonFormat, It is very similar to my current scene , Through custom annotation and field parser , Custom parsing of fields ,tql
Code
1. Custom data annotation , Data desensitization strategy can be configured
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataMasking {
DataMaskingFunc maskFunc() default DataMaskingFunc.NO_MASK;
}
2. Customize Serializer, Reference resources jackson Of StringSerializer, The following example is only for String Type for desensitization
public interface DataMaskingOperation {
String MASK_CHAR = "*";
String mask(String content, String maskChar);
}
public enum DataMaskingFunc {
/**
* Desensitization converter
*/
NO_MASK((str, maskChar) -> {
return str;
}),
ALL_MASK((str, maskChar) -> {
if (StringUtils.hasLength(str)) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
sb.append(StringUtils.hasLength(maskChar) ? maskChar : DataMaskingOperation.MASK_CHAR);
}
return sb.toString();
} else {
return str;
}
});
private final DataMaskingOperation operation;
private DataMaskingFunc(DataMaskingOperation operation) {
this.operation = operation;
}
public DataMaskingOperation operation() {
return this.operation;
}
}
public final class DataMaskingSerializer extends StdScalarSerializer<Object> {
private final DataMaskingOperation operation;
public DataMaskingSerializer() {
super(String.class, false);
this.operation = null;
}
public DataMaskingSerializer(DataMaskingOperation operation) {
super(String.class, false);
this.operation = operation;
}
public boolean isEmpty(SerializerProvider prov, Object value) {
String str = (String)value;
return str.isEmpty();
}
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
if (Objects.isNull(operation)) {
String content = DataMaskingFunc.ALL_MASK.operation().mask((String) value, null);
gen.writeString(content);
} else {
String content = operation.mask((String) value, null);
gen.writeString(content);
}
}
public final void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
this.serialize(value, gen, provider);
}
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return this.createSchemaNode("string", true);
}
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
this.visitStringFormat(visitor, typeHint);
}
}
3. Customize AnnotationIntrospector, Adapt our custom annotation to return the corresponding Serializer
@Slf4j
public class DataMaskingAnnotationIntrospector extends NopAnnotationIntrospector {
@Override
public Object findSerializer(Annotated am) {
DataMasking annotation = am.getAnnotation(DataMasking.class);
if (annotation != null) {
return new DataMaskingSerializer(annotation.maskFunc().operation());
}
return null;
}
}
4. Cover ObjectMapper
@Configuration(
proxyBeanMethods = false
)
public class DataMaskConfiguration {
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
static class JacksonObjectMapperConfiguration {
JacksonObjectMapperConfiguration() {
}
@Bean
@Primary
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
AnnotationIntrospector ai = objectMapper.getSerializationConfig().getAnnotationIntrospector();
AnnotationIntrospector newAi = AnnotationIntrospectorPair.pair(ai, new DataMaskingAnnotationIntrospector());
objectMapper.setAnnotationIntrospector(newAi);
return objectMapper;
}
}
}
5. Return the object and annotate it
public class User implements Serializable {
/**
* Primary key ID
*/
private Long id;
/**
* full name
*/
@DataMasking(maskFunc = DataMaskingFunc.ALL_MASK)
private String name;
/**
* Age
*/
private Integer age;
/**
* mailbox
*/
@DataMasking(maskFunc = DataMaskingFunc.ALL_MASK)
private String email;
}

边栏推荐
- 正方形数组的数目(DAY 81)
- “满五唯一”和“满二唯一”是什么?有什么不同?
- After two years of graduation, I switched to software testing and got 12k+, and my dream of not taking the postgraduate entrance examination with a monthly salary of more than 10000 was realized
- Data Lake (20): Flink is compatible with iceberg, which is currently insufficient, and iceberg is compared with Hudi
- cocos小游戏实战-04-碰撞检测与NPC渲染
- 177. The nth highest salary (simple)
- AcWing 2074. 倒计数 模拟
- opiodr aborting process unknown ospid (21745) as a result of ORA-609
- 抖音服务器带宽有多大,才能供上亿人同时刷?
- 记录一次,php程序访问系统文件访问错误的问题
猜你喜欢

Plato farm has a new way of playing, and the arbitrage eplato has secured super high returns

Skywalking系列学习之告警通知源码分析

Social wechat applet of fanzhihu forum community

抖音服务器带宽有多大,才能供上亿人同时刷?

spark:地区广告点击量排行统计(小案例)

Compile and use protobuf Library in vs2019

“date: write error: No space left on device”解决

Yilingsi T35 FPGA drives LVDS display screen

太强了,一个注解搞定接口返回数据脱敏

Baidu cloud face recognition
随机推荐
二叉树(北京邮电大学机试题)(DAY 85)
在线问题反馈模块实战(十五):实现在线更新反馈状态功能
[hash table] question collection
196. Delete duplicate email addresses
spark学习笔记(六)——sparkcore核心编程-RDD行动算子
Social wechat applet of fanzhihu forum community
impala 执行计划详解
抖音服务器带宽有多大,才能供上亿人同时刷?
自己梳理的LocalDateTime的工具类
一个测试类了解BeanUtils.copyProperties
数据库红的表如何设计才能使性能更加优化
Sqlserver select * can you exclude a field
Single case mode (double check lock)
2513: Xiao Yong's academic score (common divisor problem)
最低票价(DAY 80)
MySQL:互联网公司常用分库分表方案汇总
带你了解什么是 Web3.0
How to visit the latest version of burpsuite pro in vain
[learning notes, dog learning C] string + memory function
Abbkine AbFluor 488 细胞凋亡检测试剂盒特点及实验建议