0
点赞
收藏
分享

微信扫一扫

Node.js工程师养成计划内涵源码

Node.js工程师养成计划内涵源码

download:​​http://www.51xuebc.com/thread-447-1-1.html​​

对接口返回的数据脱敏是如此简单。

背景

正要钓鱼的时候,突然看到产品慢慢过来,我就觉得不好了。他没说话,我说我做不到。我做不到。他转身回去了。过了一会儿,美妆产品经理慢慢来了。她没说话,我说什么都行。直接提出需求很简单。

就是一些接口返回的信息。如果涉及敏感数据,必须脱敏。我认为相反,这意味着什么。我会立即安排。

思考


要用可配置的多策略进行脱敏操作,否则脱敏操作会一个接口一个接口的进行,重复工作量太大,明显违背了程序员“多写一行算我输”的准则。


想一想,定义数据脱敏标注和数据脱敏逻辑的接口,将需要脱敏的属性添加到返回类中,并指定相应的脱敏策略操作。


接下来我只需要截取控制器返回的数据,找到带有脱敏注释的属性操作。一开始打算用@ControllerAdvice来实现,但是发现需要自己去reflection类获取注释。


当返回的对象比较复杂,需要递归来体现的时候,性能会一下子降低,所以我想到了通常的@JsonFormat,和我现在的场景很像。我可以通过自定义注释和字段解析器自定义字段解析。

实现代码

1.可以配置用户定义的数据注释和数据脱敏策略:

@Target({ElementType。字段,元素类型。类型})

@保留(RetentionPolicy。运行时间)

@已记录

公共@接口数据屏蔽{


DataMaskingFunc maskFunc()缺省值。NO _ MASK


}

复制代码

二:自定义序列化器,参考jackson的StringSerializer。下面的示例只降低了字符串类型的敏感度。

公共接口数据屏蔽操作{


String MASK _ CHAR = " *


字符串掩码(字符串内容,字符串mask char);


}



公共枚举数据掩码Func {


/**

*脱敏转换器

*/

NO_MASK((str,maskChar) -> {

返回字符串;

}),

ALL_MASK((str,maskChar) -> {

if(string utils . haslength(str)){

StringBuilder sb = new StringBuilder();

for(int I = 0;我

sb . append(string utils . haslength(mask char)?mask char:datamaskingpoperation。MASK _ CHAR);

}

return sb . tostring();

}否则{

返回字符串;

}

});


私有最终数据屏蔽操作操作;


私有DataMaskingFunc(datamaskingpoperation操作){

this.operation =操作;

}


公共数据屏蔽操作操作(){

返回this.operation

}


}



公共最终类DataMaskingSerializer扩展了StdScalarSerializer {

私有最终数据屏蔽操作操作;


公共datamaskinserializer(){

super(String.class,false);

this.operation = null

}


公共DataMaskingSerializer(datamaskingpoperation操作){

super(String.class,false);

this.operation =操作;

}



public boolean isEmpty(serializer provider prov,Object value) {

String str =(字符串)值;

返回str . isempty();

}


公共void serialize(对象值,JsonGenerator gen,SerializerProvider provider)引发IOException {

if (Objects.isNull(operation)) {

String content = DataMaskingFunc。ALL_MASK.operation()。mask((字符串)值,null);

gen.writeString(内容);

}否则{

String content = operation . mask((String)value,null);

gen.writeString(内容);

}

}


public final void serializeWithType(对象值、JsonGenerator gen、SerializerProvider、TypeSerializer typeSer)引发IOException {

this.serialize(value,gen,provider);

}


public JSON node get schema(serializer provider provider,typeHint) {

返回this . createschemdanode(" string ",true);

}


public void acceptjsonformattivisitor(JsonFormatVisitorWrapper visitor,JavaType typeHint)抛出JsonMappingException {

this.visitStringFormat(visitor,type hint);

}

}

复制代码

第三,定制AnnotationIntrospector,并修改我们定制的注释以返回相应的序列化程序。

@Slf4j

公共类DataMaskingAnnotationIntrospector扩展了NopAnnotationIntrospector {


@覆盖

公共对象findSerializer(带注释的am) {

data masking annotation = am . get annotation(data masking . class);

如果(注释!= null) {

返回新的DataMaskingSerializer(annotation . mask func()。operation());

}

返回null

}


}

复制代码

四:覆盖对象映射器:

@配置(

proxyBeanMethods = false

)

公共类数据掩码配置{


@配置(

proxyBeanMethods = false

)

@ conditional class({ Jackson 2 objectmapper builder . class })

静态类JacksonObjectMapperConfiguration {

JacksonObjectMapperConfiguration(){

}


@Bean

@主要

对象映射器jacksonObjectMapper(Jackson 2 ObjectMapper builder生成器){

object mapper object mapper = builder . createxml mapper(false)。build();

AnnotationIntrospector ai = object mapper . getserializationconfig()。getAnnotationIntrospector();

AnnotationIntrospector newAi = AnnotationIntrospector pair . pair(ai,new datamaskingantionintrospector());

object mapper . setannotationintrospector(newAi);

返回objectMapper

}

}


}

复制代码

五:带注释返回对象:

公共类用户实现可序列化{

/**

*主键ID

*/

私有长id;


/**

*姓名

*/

@ data masking(mask func = DataMaskingFunc。ALL_MASK)

私有字符串名称;


/**

*年龄

*/

私有整数年龄;


/**

*邮箱

*/

@ data masking(mask func = DataMaskingFunc。ALL_MASK)

私人字符串电子邮件;


}


举报

相关推荐

0 条评论