Java 數據脫敏

數據脫敏

數據脫敏又稱數據去隱私化或數據變形,是在給定的規則、策略下對敏感數據進行變換、修改的技術機制,可以在很大程度上解決敏感數據在非可信環境中使用的問題。根據數據保護規範和脫敏策略.對業務數據中的敏感信息實施自動變形.實現對敏感信息的隱藏。java

脫敏方法

項目是在controller層進行脫敏,查閱google和github有兩種較爲方便的方法git

  1. 一種是基於註解 desensitized基於註解的形式進行脫敏 GitHub
  2. 一種是基於框架本質上仍是註解,可是已經封裝好了,固然還提供fastjson的方式進行脫敏 sensitive框架進行脫敏 GitHub
    因爲項目緣由不想引入框架,因此使用基於註解的方式

實現

新建枚舉類型,標明是何種脫敏方式github

package com.blgroup.vision.common.enums;

/**
 * @program: blgroup-scloud-web
 * @description: 脫敏枚舉
 * @author: ingxx
 * @create: 2019-12-17 14:32
 **/
public enum SensitiveTypeEnum {
    /**
     * 中文名
     */
    CHINESE_NAME,
    /**
     * 身份證號
     */
    ID_CARD,
    /**
     * 座機號
     */
    FIXED_PHONE,
    /**
     * 手機號
     */
    MOBILE_PHONE,
    /**
     * 地址
     */
    ADDRESS,
    /**
     * 電子郵件
     */
    EMAIL,
    /**
     * 銀行卡
     */
    BANK_CARD,
    /**
     * 虛擬帳號
     */
    ACCOUNT,
    /**
     * 密碼
     */
    PASSWORD;
}

建立註解,標識須要脫敏的字段web

package com.blgroup.vision.common.annotation;


import com.blgroup.vision.common.enums.SensitiveTypeEnum;

import java.lang.annotation.*;

/**
 * @program: blgroup-scloud-web
 * @description: 脫敏註解
 * @author: ingxx
 * @create: 2019-12-17 14:32
 **/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Desensitized {

    /*脫敏類型(規則)*/
    SensitiveTypeEnum type();

    /*判斷註解是否生效的方法*/
    String isEffictiveMethod() default "";

}

建立Object工具類,用於複製對象和對對象的其餘操做,注意使用fastjson實現深拷貝對於複雜的對象會出現棧溢出,本人測試是發生在轉換對象時對象會轉換成JsonObject對象,在getHash方法中出現遞歸調用致使棧溢出,具體緣由不明apache

package com.blgroup.vision.common.utils;

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

import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;
/**
 * @program: blgroup-scloud-web
 * @description: 脫敏Object工具類
 * @author: ingxx
 * @create: 2019-12-17 14:32
 **/
public class DesensitizedObjectUtils {

    /**
     * 用序列化-反序列化方式實現深克隆
     * 缺點:一、被拷貝的對象必需要實現序列化
     *
     * @param obj
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T deepCloneObject(T obj) {
        T t = (T) new Object();
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(obj);
            out.close();
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            t = (T) in.readObject();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 用序列化-反序列化的方式實現深克隆
     * 缺點:一、當實體中存在接口類型的參數,而且這個接口指向的實例爲枚舉類型時,會報錯"com.alibaba.fastjson.JSONException: syntax error, expect {, actual string, pos 171, fieldName iLimitKey"
     *
     * @param objSource
     * @return
     */
    public static Object deepCloneByFastJson(Object objSource) {
        String tempJson = JSON.toJSONString(objSource);
        Object clone = JSON.parseObject(tempJson, objSource.getClass());
        return clone;
    }

    /**
     * 深度克隆對象
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Object deepClone(Object objSource) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        if (null == objSource) return null;
        //是否jdk類型、基礎類型、枚舉類型
        if (isJDKType(objSource.getClass())
                || objSource.getClass().isPrimitive()
                || objSource instanceof Enum<?>) {
            if ("java.lang.String".equals(objSource.getClass().getName())) {//目前只支持String類型深複製
                return new String((String) objSource);
            } else {
                return objSource;
            }
        }
        // 獲取源對象類型
        Class<?> clazz = objSource.getClass();
        Object objDes = clazz.newInstance();
        // 得到源對象全部屬性
        Field[] fields = getAllFields(objSource);
        // 循環遍歷字段,獲取字段對應的屬性值
        for (Field field : fields) {
            field.setAccessible(true);
            if (null == field) continue;
            Object value = field.get(objSource);
            if (null == value) continue;
            Class<?> type = value.getClass();
            if (isStaticFinal(field)) {
                continue;
            }
            try {

                //遍歷集合屬性
                if (type.isArray()) {//對數組類型的字段進行遞歸過濾
                    int len = Array.getLength(value);
                    if (len < 1) continue;
                    Class<?> c = value.getClass().getComponentType();
                    Array newArray = (Array) Array.newInstance(c, len);
                    for (int i = 0; i < len; i++) {
                        Object arrayObject = Array.get(value, i);
                        Array.set(newArray, i, deepClone(arrayObject));
                    }
                } else if (value instanceof Collection<?>) {
                    Collection newCollection = (Collection) value.getClass().newInstance();
                    Collection<?> c = (Collection<?>) value;
                    Iterator<?> it = c.iterator();
                    while (it.hasNext()) {
                        Object collectionObj = it.next();
                        newCollection.add(deepClone(collectionObj));
                    }
                    field.set(objDes, newCollection);
                    continue;
                } else if (value instanceof Map<?, ?>) {
                    Map newMap = (Map) value.getClass().newInstance();
                    Map<?, ?> m = (Map<?, ?>) value;
                    Set<?> set = m.entrySet();
                    for (Object o : set) {
                        Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
                        Object mapVal = entry.getValue();
                        newMap.put(entry.getKey(), deepClone(mapVal));
                    }
                    field.set(objDes, newMap);
                    continue;
                }

                //是否jdk類型或基礎類型
                if (isJDKType(field.get(objSource).getClass())
                        || field.getClass().isPrimitive()
                        || isStaticType(field)
                        || value instanceof Enum<?>) {
                    if ("java.lang.String".equals(value.getClass().getName())) {//目前只支持String類型深複製
                        field.set(objDes, new String((String) value));
                    } else {
                        field.set(objDes, field.get(objSource));
                    }
                    continue;
                }

                //是否枚舉
                if (value.getClass().isEnum()) {
                    field.set(objDes, field.get(objSource));
                    continue;
                }

                //是否自定義類
                if (isUserDefinedType(value.getClass())) {
                    field.set(objDes, deepClone(value));
                    continue;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return objDes;
    }


    /**
     * 是否靜態變量
     *
     * @param field
     * @return
     */
    private static boolean isStaticType(Field field) {
        return field.getModifiers() == 8 ? true : false;
    }

    private static boolean isStaticFinal(Field field) {
        return Modifier.isFinal(field.getModifiers()) && Modifier.isStatic(field.getModifiers());
    }

    /**
     * 是否jdk類型變量
     *
     * @param clazz
     * @return
     * @throws IllegalAccessException
     */
    private static boolean isJDKType(Class clazz) throws IllegalAccessException {
        //Class clazz = field.get(objSource).getClass();
        return org.apache.commons.lang3.StringUtils.startsWith(clazz.getPackage().getName(), "javax.")
                || org.apache.commons.lang3.StringUtils.startsWith(clazz.getPackage().getName(), "java.")
                || org.apache.commons.lang3.StringUtils.startsWith(clazz.getName(), "javax.")
                || org.apache.commons.lang3.StringUtils.startsWith(clazz.getName(), "java.");
    }

    /**
     * 是否用戶自定義類型
     *
     * @param clazz
     * @return
     */
    private static boolean isUserDefinedType(Class<?> clazz) {
        return
                clazz.getPackage() != null
                        && !org.apache.commons.lang3.StringUtils.startsWith(clazz.getPackage().getName(), "javax.")
                        && !org.apache.commons.lang3.StringUtils.startsWith(clazz.getPackage().getName(), "java.")
                        && !org.apache.commons.lang3.StringUtils.startsWith(clazz.getName(), "javax.")
                        && !StringUtils.startsWith(clazz.getName(), "java.");
    }

    /**
     * 獲取包括父類全部的屬性
     *
     * @param objSource
     * @return
     */
    public static Field[] getAllFields(Object objSource) {
        /*得到當前類的全部屬性(private、protected、public)*/
        List<Field> fieldList = new ArrayList<Field>();
        Class tempClass = objSource.getClass();
        while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {//當父類爲null的時候說明到達了最上層的父類(Object類).
            fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass(); //獲得父類,而後賦給本身
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    /**
     * 深度克隆對象
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Deprecated
    public static Object copy(Object objSource) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {

        if (null == objSource) return null;
        // 獲取源對象類型
        Class<?> clazz = objSource.getClass();
        Object objDes = clazz.newInstance();
        // 得到源對象全部屬性
        Field[] fields = getAllFields(objSource);
        // 循環遍歷字段,獲取字段對應的屬性值
        for (Field field : fields) {
            field.setAccessible(true);
            // 若是該字段是 static + final 修飾
            if (field.getModifiers() >= 24) {
                continue;
            }
            try {
                // 設置字段可見,便可用get方法獲取屬性值。
                field.set(objDes, field.get(objSource));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return objDes;
    }
}

建立脫敏工具類json

package com.blgroup.vision.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.blgroup.vision.common.annotation.Desensitized;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
/**
 * @program: blgroup-scloud-web
 * @description: 脫敏工具類
 * @author: ingxx
 * @create: 2019-12-17 14:32
 **/
public class DesensitizedUtils{

    /**
     * 獲取脫敏json串(遞歸引用會致使java.lang.StackOverflowError)
     *
     * @param javaBean
     * @return
     */
    public static String getJson(Object javaBean) {
        String json = null;
        if (null != javaBean) {
            try {
                if (javaBean.getClass().isInterface()) return json;
                /* 克隆出一個實體進行字段修改,避免修改原實體 */
                //Object clone =DesensitizedObjectUtils.deepCloneObject(javaBean);
                //Object clone =DesensitizedObjectUtils.deepCloneByFastJson(javaBean);
                Object clone = DesensitizedObjectUtils.deepClone(javaBean);

                /* 定義一個計數器,用於避免重複循環自定義對象類型的字段 */
                Set<Integer> referenceCounter = new HashSet<Integer>();

                /* 對克隆實體進行脫敏操做 */
                DesensitizedUtils.replace(DesensitizedObjectUtils.getAllFields(clone), clone, referenceCounter);

                /* 利用fastjson對脫敏後的克隆對象進行序列化 */
                json = JSON.toJSONString(clone, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty);

                /* 清空計數器 */
                referenceCounter.clear();
                referenceCounter = null;
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return json;
    }

    public static <T> T getObj(T javaBean) {
        T clone = null;
        if (null != javaBean) {
            try {
                if (javaBean.getClass().isInterface()) return null;
                /* 克隆出一個實體進行字段修改,避免修改原實體 */
                //Object clone =DesensitizedObjectUtils.deepCloneObject(javaBean);
                //Object clone =DesensitizedObjectUtils.deepCloneByFastJson(javaBean);
                clone = (T) DesensitizedObjectUtils.deepClone(javaBean);

                /* 定義一個計數器,用於避免重複循環自定義對象類型的字段 */
                Set<Integer> referenceCounter = new HashSet<Integer>();

                /* 對克隆實體進行脫敏操做 */
                DesensitizedUtils.replace(DesensitizedObjectUtils.getAllFields(clone), clone, referenceCounter);

                /* 清空計數器 */
                referenceCounter.clear();
                referenceCounter = null;
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return clone;
    }

    /**
     * 對須要脫敏的字段進行轉化
     *
     * @param fields
     * @param javaBean
     * @param referenceCounter
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    private static void replace(Field[] fields, Object javaBean, Set<Integer> referenceCounter) throws IllegalArgumentException, IllegalAccessException {
        if (null != fields && fields.length > 0) {
            for (Field field : fields) {
                field.setAccessible(true);
                if (null != field && null != javaBean) {
                    Object value = field.get(javaBean);
                    if (null != value) {
                        Class<?> type = value.getClass();
                        //處理子屬性,包括集合中的
                        if (type.isArray()) {//對數組類型的字段進行遞歸過濾
                            int len = Array.getLength(value);
                            for (int i = 0; i < len; i++) {
                                Object arrayObject = Array.get(value, i);
                                if (isNotGeneralType(arrayObject.getClass(), arrayObject, referenceCounter)) {
                                    replace(DesensitizedObjectUtils.getAllFields(arrayObject), arrayObject, referenceCounter);
                                }
                            }
                        } else if (value instanceof Collection<?>) {//對集合類型的字段進行遞歸過濾
                            Collection<?> c = (Collection<?>) value;
                            Iterator<?> it = c.iterator();
                            while (it.hasNext()) {// TODO: 待優化
                                Object collectionObj = it.next();
                                if (isNotGeneralType(collectionObj.getClass(), collectionObj, referenceCounter)) {
                                    replace(DesensitizedObjectUtils.getAllFields(collectionObj), collectionObj, referenceCounter);
                                }
                            }
                        } else if (value instanceof Map<?, ?>) {//對Map類型的字段進行遞歸過濾
                            Map<?, ?> m = (Map<?, ?>) value;
                            Set<?> set = m.entrySet();
                            for (Object o : set) {
                                Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
                                Object mapVal = entry.getValue();
                                if (isNotGeneralType(mapVal.getClass(), mapVal, referenceCounter)) {
                                    replace(DesensitizedObjectUtils.getAllFields(mapVal), mapVal, referenceCounter);
                                }
                            }
                        } else if (value instanceof Enum<?>) {
                            continue;
                        }

                        /*除基礎類型、jdk類型的字段以外,對其餘類型的字段進行遞歸過濾*/
                        else {
                            if (!type.isPrimitive()
                                    && type.getPackage() != null
                                    && !StringUtils.startsWith(type.getPackage().getName(), "javax.")
                                    && !StringUtils.startsWith(type.getPackage().getName(), "java.")
                                    && !StringUtils.startsWith(field.getType().getName(), "javax.")
                                    && !StringUtils.startsWith(field.getName(), "java.")
                                    && referenceCounter.add(value.hashCode())) {
                                replace(DesensitizedObjectUtils.getAllFields(value), value, referenceCounter);
                            }
                        }
                    }

                    //脫敏操做
                    setNewValueForField(javaBean, field, value);

                }
            }
        }
    }

    /**
     * 排除基礎類型、jdk類型、枚舉類型的字段
     *
     * @param clazz
     * @param value
     * @param referenceCounter
     * @return
     */
    private static boolean isNotGeneralType(Class<?> clazz, Object value, Set<Integer> referenceCounter) {
        return !clazz.isPrimitive()
                && clazz.getPackage() != null
                && !clazz.isEnum()
                && !StringUtils.startsWith(clazz.getPackage().getName(), "javax.")
                && !StringUtils.startsWith(clazz.getPackage().getName(), "java.")
                && !StringUtils.startsWith(clazz.getName(), "javax.")
                && !StringUtils.startsWith(clazz.getName(), "java.")
                && referenceCounter.add(value.hashCode());
    }

    /**
     * 脫敏操做(按照規則轉化須要脫敏的字段並設置新值)
     * 目前只支持String類型的字段,如須要其餘類型如BigDecimal、Date等類型,能夠添加
     *
     * @param javaBean
     * @param field
     * @param value
     * @throws IllegalAccessException
     */
    public static void setNewValueForField(Object javaBean, Field field, Object value) throws IllegalAccessException {
        //處理自身的屬性
        Desensitized annotation = field.getAnnotation(Desensitized.class);
        if (field.getType().equals(String.class) && null != annotation && executeIsEffictiveMethod(javaBean, annotation)) {
            String valueStr = (String) value;
            if (StringUtils.isNotBlank(valueStr)) {
                switch (annotation.type()) {
                    case CHINESE_NAME: {
                        field.set(javaBean, DesensitizedUtils.chineseName(valueStr));
                        break;
                    }
                    case ID_CARD: {
                        field.set(javaBean, DesensitizedUtils.idCardNum(valueStr));
                        break;
                    }
                    case FIXED_PHONE: {
                        field.set(javaBean, DesensitizedUtils.fixedPhone(valueStr));
                        break;
                    }
                    case MOBILE_PHONE: {
                        field.set(javaBean, DesensitizedUtils.mobilePhone(valueStr));
                        break;
                    }
                    case ADDRESS: {
                        field.set(javaBean, DesensitizedUtils.address(valueStr, 7));
                        break;
                    }
                    case EMAIL: {
                        field.set(javaBean, DesensitizedUtils.email(valueStr));
                        break;
                    }
                    case BANK_CARD: {
                        field.set(javaBean, DesensitizedUtils.bankCard(valueStr));
                        break;
                    }
                    case PASSWORD: {
                        field.set(javaBean, DesensitizedUtils.password(valueStr));
                        break;
                    }case ACCOUNT:{
                        field.set(javaBean, DesensitizedUtils.account(valueStr));
                        break;
                    }
                }
            }
        }
    }

    /**
     * 執行某個對象中指定的方法
     *
     * @param javaBean     對象
     * @param desensitized
     * @return
     */
    private static boolean executeIsEffictiveMethod(Object javaBean, Desensitized desensitized) {
        boolean isAnnotationEffictive = true;//註解默認生效
        if (desensitized != null) {
            String isEffictiveMethod = desensitized.isEffictiveMethod();
            if (isNotEmpty(isEffictiveMethod)) {
                try {
                    Method method = javaBean.getClass().getMethod(isEffictiveMethod);
                    method.setAccessible(true);
                    isAnnotationEffictive = (Boolean) method.invoke(javaBean);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return isAnnotationEffictive;
    }

    private static boolean isNotEmpty(String str) {
        return str != null && !"".equals(str);
    }

    private static boolean isEmpty(String str) {
        return !isNotEmpty(str);
    }

    /**
     * 【中文姓名】只顯示第一個漢字,其餘隱藏爲2個星號,好比:李**
     *
     * @param fullName
     * @return
     */
    public static String chineseName(String fullName) {
        if (StringUtils.isBlank(fullName)) {
            return "";
        }
        String name = StringUtils.left(fullName, 1);
        return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
    }

    /**
     * 【身份證號】顯示第一位和最後一位
     *
     * @param id
     * @return
     */
    public static String idCardNum(String id) {
        if (StringUtils.isBlank(id)) {
            return "";
        }
        return StringUtils.left(id,1).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(id,1), StringUtils.length(id),"*"),"*"));
    }

    /**
     * 【虛擬帳號】顯示第一位和最後一位
     *
     * @param id
     * @return
     */
    public static String account(String id) {
        if (StringUtils.isBlank(id)) {
            return "";
        }
        return StringUtils.left(id,1).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(id,1), StringUtils.length(id),"*"),"*"));
    }


    /**
     * 【固定電話 後四位,其餘隱藏,好比1234
     *
     * @param num
     * @return
     */
    public static String fixedPhone(String num) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
    }

    /**
     * 【手機號碼】前三位,後四位,其餘隱藏,好比135****6810
     *
     * @param num
     * @return
     */
    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), "*"), "***"));
    }

    /**
     * 【地址】只顯示到地區,不顯示詳細地址,好比:北京市海淀區****
     *
     * @param address
     * @param sensitiveSize 敏感信息長度
     * @return
     */
    public static String address(String address, int sensitiveSize) {
        if (StringUtils.isBlank(address)) {
            return "";
        }
        int length = StringUtils.length(address);
        return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
    }

    /**
     * 【電子郵箱 郵箱前綴僅顯示第一個字母,前綴其餘隱藏,用星號代替,@及後面的地址顯示,好比:d**@126.com>
     *
     * @param email
     * @return
     */
    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)));
    }

    /**
     * 【銀行卡號】前4位,後3位,其餘用星號隱藏每位1個星號,好比:6217 **** **** **** 567>
     *
     * @param cardNum
     * @return
     */
    public static String bankCard(String cardNum) {
        if (StringUtils.isBlank(cardNum)) {
            return "";
        }
            return StringUtils.left(cardNum, 4).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 3), StringUtils.length(cardNum), "*"), "****"));
    }

    /**
     * 【密碼】密碼的所有字符都用*代替,好比:******
     *
     * @param password
     * @return
     */
    public static String password(String password) {
        if (StringUtils.isBlank(password)) {
            return "";
        }
        String pwd = StringUtils.left(password, 0);
        return StringUtils.rightPad(pwd, StringUtils.length(password), "*");
    }

    /**
     * 遍歷List脫敏數據
     * @param content
     * @return
     */
    public static <T> List getList(List<T> content){
        if (content == null || content.size() <= 0) {
            return content;
        }
        List list = new ArrayList<T>();
        for (T t : content) {
            list.add(getObj(t));
        }
        return list;
    }
}

效果展現

因生產項目中不能展現 因此採用Demo的形式數組

建立測試實體類框架

package top.ingxx.pojo;

import lombok.Data;
import top.ingxx.annotation.Desensitized;
import top.ingxx.enums.SensitiveTypeEnum;

@Data
public class UserInfo {
    @Desensitized(type = SensitiveTypeEnum.CHINESE_NAME)
    private String realName;

    @Desensitized(type = SensitiveTypeEnum.ID_CARD)
    private String idCardNo;

    @Desensitized(type = SensitiveTypeEnum.MOBILE_PHONE)
    private String mobileNo;

    @Desensitized(type = SensitiveTypeEnum.ADDRESS)
    private String address;

    @Desensitized(type = SensitiveTypeEnum.PASSWORD)
    private String password;

    @Desensitized(type = SensitiveTypeEnum.BANK_CARD)
    private String bankCard;
}

測試實體字段工具

package top.ingxx.pojo;

import lombok.Data;

/**
 * @program: demo
 * @description: 測試
 * @author: ingxx
 * @create: 2019-12-18 09:16
 **/
@Data
public class Test {
    private UserInfo userInfo;
}

測試主方法測試

import com.alibaba.fastjson.JSON;
import top.ingxx.pojo.Test;
import top.ingxx.pojo.UserInfo;
import top.ingxx.utils.DesensitizedUtils;

public class Main {

    public static void main(String[] args) {
        UserInfo userInfo = new UserInfo();
        userInfo.setAddress("上海浦東新區未知地址12號");
        userInfo.setIdCardNo("111521444474441411");
        userInfo.setMobileNo("13555551141");
        userInfo.setPassword("123456");
        userInfo.setRealName("張三");
        userInfo.setBankCard("111521444474441411");
        Test test = new Test();
        test.setUserInfo(userInfo);
        System.out.println(JSON.toJSONString(test));
        Test obj = DesensitizedUtils.getObj(test);
        System.out.println(JSON.toJSONString(obj));
    }
}

使用時能夠對單個字段脫敏 也能夠直接使用 getObj getJson getList等方法

相關文章
相關標籤/搜索