当前位置:网站首页>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;
}

边栏推荐
- Redis四大特殊数据类型的学习和理解
- Abbkine AbFluor 488 细胞凋亡检测试剂盒特点及实验建议
- spark学习笔记(六)——sparkcore核心编程-RDD行动算子
- Hcip 13th day notes
- Activiti5.22.0扩展支持达国产数据库,以GBase据库为例
- 196. Delete duplicate email addresses
- {“errcode“:44001,“errmsg“:“empty media data, hint: [1655962096234893527769663], from ip: 222.72.xxx.
- 一道数学题,让芯片巨头亏了5亿美金!
- [SQL simple question] leetcode 627. change gender
- opiodr aborting process unknown ospid (21745) as a result of ORA-609
猜你喜欢

Use the most primitive method to manually implement the common 20 array methods

CAS deployment and successful login jump address

win10/win11无损扩大C盘空间,跨盘合并C、E盘

易灵思T35 FPGA驱动LVDS显示屏

cocos小游戏实战-04-碰撞检测与NPC渲染

Compile and use protobuf Library in vs2019
The most complete basic knowledge of software testing in the whole network (a must for beginners)

Hcip day 14 notes

Portraiture5 new and upgraded leather filter plug-in artifact

Abbkine AbFluor 488 细胞凋亡检测试剂盒特点及实验建议
随机推荐
最低票价(DAY 80)
自己梳理的LocalDateTime的工具类
Plato Farm全新玩法,套利ePLATO稳获超高收益
The most complete basic knowledge of software testing in the whole network (a must for beginners)
一道数学题,让芯片巨头亏了5亿美金!
be based on. NETCORE development blog project starblog - (16) some new functions (monitoring / statistics / configuration / initialization)
Naive Bayes -- Document Classification
A test class understands beanutils.copyproperties
在线问题反馈模块实战(十五):实现在线更新反馈状态功能
sqlserver select * 能不能排除某个字段
Source code analysis of warning notification for skywalking series learning
Bulk copy baby upload prompt garbled, how to solve?
My crawler notes (VII) blog traffic +1 through Crawlers
Leetcode 207. curriculum (July 26, 2022)
[hash table] question collection
排列与二进制(吉,大)(DAY 84)
“date: write error: No space left on device”解决
关于OpenFeign的源码分析
Single case mode (double check lock)
最大连续子序列(DAY 77)