数据脱敏实现

发布时间 2023-07-08 19:15:45作者: dengyy

  数据脱敏是对分为数据库数据脱敏与接口脱敏。其中数据库入库数据脱敏方式我们一般采用对称加密来实现数据脱敏,接口脱敏我们一般用遮罩方式实现数据脱敏比如用“*”占位。本文章主要介绍接口脱敏方式。

 1.定义一个自定义注解类

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Desensitized {
    SensitiveTypeEnum type();
    String isEffictiveMethod() default "";
}

2.定义脱敏枚举类

public enum SensitiveTypeEnum {
    CHINESE_NAME,
    ID_CRAD_NUM,
    FIXED_PHONE,
    MOBILE_PHONE,
    CAR_NUMBER,
    ADDRESS,
    EMAIL,
    BANK_CARD,
    PASSWORD;
}

2.定义脱敏工具类

    该工具我们采用反射扫描数据对象实体上的Desensitized注解,通过类型作为一种策略加载不同类型字符串的脱敏Bean来实现数据脱敏 

@Slf4j
public class DesensitizedUtil {

    public static void setNewValueForField(Object javaBean, Field field,Object value) {
        Desensitized annotation = field.getAnnotation(Desensitized.class);
        if (field.getType().equals(String.class) && null != annotation && executeIsEffictiveMethod(javaBean,annotation)) {
            String valueStr = (String) value;
            if (StrUtil.isNotBlank(valueStr)) {
                try {
                    String beanName = lowerLineToHump(annotation.type().toString())+ "Desensitized";
                    AbstractDesensitized desensitized = (AbstractDesensitized) SpringUtil.getBean(beanName);
                    field.set(javaBean,desensitized.handler(javaBean,valueStr));
                } catch (IllegalAccessException var7) {
                    log.error("[core CcbDesitizedUtil executeIsEffictiveMethod IllegalAccessException]:error={}",var7.getMessage(),var7);
                }
            }
        }
    }

    public static Boolean executeIsEffictiveMethod(Object javaBean, Desensitized desensitized) {
        boolean isAnnotationEffictive = true;
        if (desensitized != null) {
            String isEffictiveMethod = desensitized.isEffictiveMethod();
            if (StrUtil.isNotEmpty(isEffictiveMethod)) {
                try {
                    Method method = javaBean.getClass().getMethod(isEffictiveMethod);
                    method.setAccessible(true);
                    isAnnotationEffictive = (Boolean) method.invoke(javaBean);
                } catch (NoSuchMethodException var5) {
                    log.error("[core CcbDesitizedUtil executeIsEffictiveMethod NoSuchMethodException]:error={}",var5.getMessage(),var5);
                } catch (InvocationTargetException var6) {
                    log.error("[core CcbDesitizedUtil executeIsEffictiveMethod InvocationTargetException]:error={}",var6.getMessage(),var6);
                } catch (IllegalAccessException var7) {
                    log.error("[core CcbDesitizedUtil executeIsEffictiveMethod IllegalAccessException]:error={}",var7.getMessage(),var7);
                }
            }
        }
        return isAnnotationEffictive;
    }

    public static String lowerLineToHump(String lowerLineAndUppercaseStr) {
        //拆分成数组
        String[] eachStr = lowerLineAndUppercaseStr.split("_");
        StringBuilder resStr = new StringBuilder();
        String firstStr = "";
        String tempStr = "";
        for (int i = 0; i < eachStr.length; i++) {
            //第一个数组全部小写
            if (i == 0) {
                firstStr = eachStr[0].toLowerCase();
                resStr.append(firstStr);
            } else {
                //以后的数组首字母大写
                tempStr = capitalizeTheFirstLetter(eachStr[i]);
                resStr.append(tempStr);
            }
        }

        return resStr.toString();
    }

    public static String capitalizeTheFirstLetter(String str) {
        char firstChar = str.toUpperCase().charAt(0);
        String nextStr = str.toLowerCase().substring(1);
        return firstChar + nextStr;
    }
}

3、脱敏处理类

抽象处理接口

public abstract class AbstractDesensitized {
    public abstract String handler(Object javaBean,String valueStr);
}

身份证加密方式

@Slf4j
@Component
public class IdCardNumDesensitized extends AbstractDesensitized {
    @Override
    public String handler(Object javaBean, String id) {
        if (StrUtil.isNotBlank(id)) {
            String num = StringUtils.rightPad(id, 4);
            return StringUtils.rightPad(num, StringUtils.length(id), "*");
        }
        return "";
    }
}

4.使用说明:在进行扩展时,先定义对应的枚举,然后实现数据脱敏处理接口,即可进行扩展。