一键下班(二)数据脱敏

350 阅读2分钟

使用场景

字段脱敏(Field Masking)是一种数据保护技术,通过对敏感数据的部分或全部字符进行替换、混淆、隐藏等方式来保护数据的隐私安全。

在一个在线支付系统中,信用卡号是一种敏感数据,需要保护用户的隐私信息。通常,我们可以使用字段脱敏技术来隐藏信用卡号的部分数字,使得敏感信息不会被恶意利用。例如,将信用卡号中的中间12位数字替换成星号(*)。

解决思路

利用jackson序列化和注解对字段进行处理

架构实现

  1. hutool
  2. jackson
  3. springboot

解决方法

话不多说,直接上注解 @Desensitize

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizeSerializer.class)
public @interface Desensitize {
​
    DesensitizeEnum value();
​
}

然后实现 DesensitizeSerializer.classDesensitizeEnum.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;
    
}

image.png

好!!!下班回家