• Basic desensitization field
/** * @date 2020/9/29 16:22 */ public class BaseField implements Serializable {private static final Long serialVersionUID = 1; /** ** @desensitizedAnnotation (type = typeene.chinese_name) private String username; /** * Mobile phone number */ @desensiTIZedAnnotation (type = TypeEnum.MOBILE_PHONE) private String phone; /** * PASSWORD */ @desensitizedAnnotation (type = TypeEnum.PASSWORD) private String PASSWORD; /** * ADDRESS */ @desensiTizedAnnotation (type = TypeEnum.ADDRESS) private String ADDRESS; /** * @desensitizedAnnotation (type = TypeEnum.BANKCARD) private String BANKCARD; /** * @desensiTIZedAnnotation (type = TypeEnum.EMAIL) private String EMAIL; /** * fixedPhone number */ @desensitizedannotation (type = TypeEnum.FIXED_PHONE) private String fixedPhone; /** * id id */ @desensitizedAnnotation (type = typeene.id_card_num) private String idCardNum; }Copy the code
  • Desensitization annotations
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface DesensitizedAnnotation {/** * desensitization data type(rule) */ TypeEnum type(); }Copy the code
  • Enumeration class
Public enum TypeEnum {/** * name **/ CHINESE_NAME, /** * id id **/ ID_CARD_NUM, /** * mobile id **/ MOBILE_PHONE, / * * * * / FIXED_PHONE fixed phone, / PASSWORD/PASSWORD * * * * *, * * * / bank card number * / BANKCARD, / * * * E-mail * / EMAIL,} / ADDRESS/ADDRESS * * * *,Copy the code
  • Desensitization tool class

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @date 2020/9/29 16:23
 */
public class DesensitizedUtils {

    private static final Logger logger = LoggerFactory.getLogger(DesensitizedUtils.class);

    /**
     * 存储所有需要脱敏的字段
     */
    private static final Map<String, TypeEnum> annotationMaps = new HashMap<>();

    /**
     * 类加载时装配待脱敏字段
     */
    static {
        try {
            Class<?> clazz = Class.forName(BaseField.class.getName());
            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                DesensitizedAnnotation annotation = fields[i].getAnnotation(DesensitizedAnnotation.class);
                if (annotation != null) {
                    TypeEnum type = annotation.type();
                    String name = fields[i].getName();
                    //name为注解字段名称,value为注解类型。方便后续根据注解类型扩展
                    DesensitizedUtils.annotationMaps.put(name, type);
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            DesensitizedUtils.logger.error("类加载时装配待脱敏字段异常,异常信息:[{}]", new Object[]{e});
        }
    }


    /**
     * 脱敏:可以实现Map或者JavaBean两种模式脱敏
     *
     * @param object 需要脱敏的对象
     */
    public static String desensitization(Object object) {
        String objClassName = object.getClass().getName();
        try {
            // 1.处理Map数据类型
            if (object instanceof Map) {
                HashMap<String, Object> reqMap = (HashMap) object;
                Iterator<String> iterator = DesensitizedUtils.annotationMaps.keySet().iterator();
                iterator.forEachRemaining(annotationName -> {
                    if (reqMap.keySet().contains(annotationName)) {
                        DesensitizedUtils.doconverentForMap(reqMap, annotationName);
                    }
                });
                return JSON.toJSONString(reqMap);
            }
            // 2.处理Object数据类型
            Object val = new Object();
            Class<?> objClazz = Class.forName(objClassName);
            Field[] declaredFields = objClazz.getDeclaredFields();
            for (int j = 0; j < declaredFields.length; j++) {
                Iterator<String> iterator = DesensitizedUtils.annotationMaps.keySet().iterator();
                while (iterator.hasNext()) {
                    String annotationName = iterator.next();
                    if (declaredFields[j].getName().equals(annotationName)) {
                        declaredFields[j].setAccessible(true);
                        val = declaredFields[j].get(object);
                        //获取属性后现在默认处理的是String类型,其他类型数据可扩展
                        String value = DesensitizedUtils.doconverentForObject(val, annotationName);
                        declaredFields[j].set(object, value);
                    }
                }
            }
            return JSON.toJSONString(object);
        } catch (Exception e) {
            e.printStackTrace();
            DesensitizedUtils.logger.error("日志脱敏处理失败,回滚,详细信息:[{}]", new Object[]{e});
            return JSON.toJSONString(object);
        }
    }

    /**
     * 脱敏数据源为Object(JavaBean)时处理方式
     */
    private static String doconverentForObject(Object val, String annotationName) {

        String value = String.valueOf(val);
        if (StringUtils.isNotEmpty(value)) {
            value = DesensitizedUtils.doConverentByType(value, annotationName);
        }
        return value;
    }

    /**
     * 脱敏数据源为Map时处理方式
     */
    private static void doconverentForMap(HashMap<String, Object> reqMap, String annotationName) {
        String value = String.valueOf(reqMap.get(annotationName));
        if (StringUtils.isNotEmpty(value)) {
            value = DesensitizedUtils.doConverentByType(value, annotationName);
        }
        reqMap.put(annotationName, value);
    }


    /**
     * 根据不同注解类型处理不同字段
     */
    private static String doConverentByType(String value, String annotationName) {
        TypeEnum typeEnum = DesensitizedUtils.annotationMaps.get(annotationName);
        switch (typeEnum) {
            case CHINESE_NAME:
                value = DesensitizedUtils.chineseName(value);
                break;
            case ID_CARD_NUM:
                value = DesensitizedUtils.idCardNum(value);
                break;
            case MOBILE_PHONE:
                value = DesensitizedUtils.mobilePhone(value);
                break;
            case FIXED_PHONE:
                value = DesensitizedUtils.fixedPhone(value);
                break;
            case PASSWORD:
                value = DesensitizedUtils.password(value);
                break;
            case BANKCARD:
                value = DesensitizedUtils.bankCard(value);
                break;
            case EMAIL:
                value = DesensitizedUtils.email(value);
                break;
            case ADDRESS:
                value = DesensitizedUtils.address(value);
                break;
        }
        return value;
    }

    /*--------------------------下面的脱敏工具类也可以单独对某一个字段进行使用-------------------------*/

    /**
     * 【中文姓名】只显示第一个汉字,其他隐藏为2个星号,比如:李**
     */
    public static String chineseName(String fullName) {
        if (StringUtils.isBlank(fullName)) {
            return "";
        }
        String name = StringUtils.left(fullName, 1);
        return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
    }

    /**
     * 【身份证号】显示最后四位,其他隐藏。共计18位或者15位,比如:*************1234
     */
    public static String idCardNum(String id) {
        if (StringUtils.isBlank(id)) {
            return "";
        }
        String num = StringUtils.right(id, 4);
        return StringUtils.leftPad(num, StringUtils.length(id), "*");
    }

    /**
     * 【固定电话】 显示后四位,其他隐藏,比如:*******3241
     */
    public static String fixedPhone(String num) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
    }

    /**
     * 【手机号码】前三位,后四位,其他隐藏,比如:135****6810
     */
    public static String mobilePhone(String num) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), "***"));
    }

    /**
     * 【地址】只显示到地区,不显示详细地址,比如:湖南省长沙市岳麓区***
     */
    public static String address(String address) {
        int sensitiveSize = 8;
        if (StringUtils.isBlank(address)) {
            return "";
        }
        int length = StringUtils.length(address);
        return StringUtils.rightPad(StringUtils.left(address, (length - sensitiveSize) < 0 ? 0 : length - sensitiveSize), length, "*");
    }

    /**
     * 【电子邮箱】 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.com
     */
    public static String email(String email) {
        if (StringUtils.isBlank(email)) {
            return "";
        }
        int index = StringUtils.indexOf(email, "@");
        if (index <= 1) {
            return email;
        } else {
            return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));
        }
    }

    /**
     * 【银行卡号】前六位,后四位,其他用星号隐藏每位1个星号,比如:6222600**********1234
     */
    public static String bankCard(String cardNum) {
        if (StringUtils.isBlank(cardNum)) {
            return "";
        }
        return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
    }

    /**
     * 【密码】密码的全部字符都用*代替,比如:******
     */
    public static String password(String password) {
        if (StringUtils.isBlank(password)) {
            return "";
        }
        String pwd = StringUtils.left(password, 0);
        return StringUtils.rightPad(pwd, StringUtils.length(password), "*");
    }
}
Copy the code
  • test

person

== Note: == business entities need to desensitize the same fields as in the BaseFiled class

@Data
public class Person implements Serializable {
    private String id;

    private String username;

    private String password;

    private String phone;

    private String address;
}
Copy the code

TestController

@RestController public class TestController { @PostMapping("hello") public Person test() { Person person = new Person();  person.setId("1"); Person. SetUsername (" zhang "); person.setPassword("123456"); person.setPhone("18888888888"); Person.setaddress (" Yuelu Business Square, Changsha city, Hunan Province "); System.out.println(" desensitization: "+ person); DesensitizedUtils.desensitization(person); HashMap<String, Object> map = new HashMap<>(16); Map. put("username", "xiaozhang "); map.put("password", "123456789"); map.put("phone", "18888888888"); Map. Put ("address", "yuelu Square, Changsha city, Hunan Province "); DesensitizedUtils.desensitization(map); return person; }}Copy the code