使用场景
字段脱敏(Field Masking)是一种数据保护技术,通过对敏感数据的部分或全部字符进行替换、混淆、隐藏等方式来保护数据的隐私安全。
在一个在线支付系统中,信用卡号是一种敏感数据,需要保护用户的隐私信息。通常,我们可以使用字段脱敏技术来隐藏信用卡号的部分数字,使得敏感信息不会被恶意利用。例如,将信用卡号中的中间12位数字替换成星号(*)。
解决思路
利用jackson序列化和注解对字段进行处理
架构实现
- hutool
- jackson
- springboot
解决方法
话不多说,直接上注解 @Desensitize
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizeSerializer.class)
public @interface Desensitize {
DesensitizeEnum value();
}
然后实现 DesensitizeSerializer.class 和 DesensitizeEnum.class
public enum DesensitizeEnum {
//用户id
USER_ID(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.USER_ID)),
//中文名
CHINESE_NAME(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.CHINESE_NAME)),
//身份证号
ID_CARD(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.ID_CARD)),
//座机号
FIXED_PHONE(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.FIXED_PHONE)),
//手机号
MOBILE_PHONE(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.MOBILE_PHONE)),
//地址
ADDRESS(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.ADDRESS)),
//电子邮件
EMAIL(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.EMAIL)),
//密码
PASSWORD(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.PASSWORD)),
//中国大陆车牌,包含普通车辆、新能源车辆
CAR_LICENSE(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.CAR_LICENSE)),
//银行卡
BANK_CARD(s -> DesensitizedUtil.desensitized(s, DesensitizedUtil.DesensitizedType.BANK_CARD));
private Function<String, String> function;
DesensitizeEnum(Function<String, String> function) {
this.function = function;
}
public Function<String, String> function() {
return this.function;
}
}
public class DesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {
private DesensitizeEnum dese;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(dese.function().apply(value));
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
Desensitize annotation = property.getAnnotation(Desensitize.class);
Map<String, String> map = DesensitizeOperator.get();
if (ObjectUtil.isNotNull(annotation) && Objects.equals(property.getType().getRawClass(), String.class) && (ObjectUtil.isNull(map) || !map.containsKey("skip") || !StrUtil.equals("yes",map.get("skip")))) {
this.dese = annotation.value();
return this;
}
DesensitizeOperator.remove();
return prov.findValueSerializer(property.getType(), property);
}
}
最后实现一个脱敏的实现类 DesensitizeOperator.class
public class DesensitizeOperator {
private static final ThreadLocal<Map<String, String>> context = new ThreadLocal<>();
public DesensitizeOperator(){}
public static Map<String, String> get(){return context.get();}
public static void set(Map<String, String> map){
context.set(map);
}
public static void remove(){context.remove();}
/**
* 跳过pass脱敏操作 需手动调用在方法体里即可
* <br />
*/
public static void skip(){
Map<String, String> map = new HashMap<>(16);
map.put("skip","yes");
set(map);
}
}
就这样完了是不是很简单?那我们来看看如何使用以及最终实现的效果如何
@Data
public class User implements Serializable {
/**
* 邮箱
*/
@Desensitize(value = DesensitizeEnum.EMAIL)
private String email;
/**
* 手机
*/
@Desensitize(value = DesensitizeEnum.MOBILE_PHONE)
private String phone;
}
好!!!下班回家