1. 程式人生 > >掩碼處理--方法二

掩碼處理--方法二

package com.foresee.zxpt.common.mask;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.gson.Gson;

import lombok.extern.slf4j.Slf4j;

/**
 * 資料脫敏處理工具類
 * @version 1.0
 * @date 2018年9月18日下午5:23:05
 */
@Slf4j
public class SensitiveInfoUtils {

	/**
	 * 中文名
	 */
	public static final String CHINESE_NAME="01";

	/**
	 * 身份證號
	 */
	public static final String ID_CARD="02";
	/**
	 * 座機號
	 */
	public static final String TELE_PHONE="03";
	/**
	 * 固定電話
	 */
	public static final String FIXED_PHONE="04";
	/**
	 * 手機號
	 */
	public static final String MOBILE_PHONE="05";
	/**
	 * 電話號碼(包括手機號和固定電話)
	 */
	public static final String PHONE="06";
	/**
	 * 地址
	 */
	public static final String ADDRESS="07";
	/**
	 * 電子郵件
	 */
	public static final String EMAIL="08";
	/**
	 * 銀行卡
	 */
	public static final String BANK_CARD="09";
	/**
	 * 公司開戶銀行聯號
	 */
	public static final String CNAPS_CODE="10";
	/**
	 * 車輛識別號
	 */
	public static final String CAR_CODE="11";
	/**
	 * 房源編號\土地稅源編號\土地使用證編號
	 */
	public static final String RESOURCE_CODE="12";
	/**
	 * 車牌號
	 */
	public static final String PLATE_NUMBER="13";

	/**
	 * [中文姓名] 只顯示第一個漢字,其他隱藏為2個星號<例子:李**>
	 * 
	 * @param name
	 * @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), "*");
	}

	/**
	 * [中文姓名] 只顯示第一個漢字,其他隱藏為2個星號<例子:李**>
	 * 
	 * @param familyName
	 * @param givenName
	 * @return
	 */
	public static String chineseName(String familyName, String givenName) {
		if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) {
			return "";
		}
		return chineseName(familyName + givenName);
	}

	/**
	 * [身份證號] 顯示前6後2,其他隱藏。共計18位或者15位。<例子:*************5762>
	 * 
	 * @param id
	 * @return
	 */
	public static String idCardNum(String id) {
		if (StringUtils.isBlank(id)) {
			return "";
		}
		return StringUtils.left(id, 6).concat(StringUtils
				.removeStart(StringUtils.leftPad(StringUtils.right(id, 2), StringUtils.length(id), "*"), "******"));
	}

	/**
	 * [固定電話] 後四位,其他隱藏<例子:****1234>
	 * 
	 * @param num
	 * @return
	 */
	public static String telePhone(String num) {
		if (StringUtils.isBlank(num)) {
			return "";
		}
		return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
	}

	/**
	 * [固定電話] 前兩位,後兩位,其他隱藏<例子:88**34>
	 * 
	 * @param num
	 * @return
	 */
	public static String fixedPhone(String num) {
		if (StringUtils.isBlank(num)) {
			return "";
		}
		return StringUtils.left(num, 2).concat(StringUtils
				.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "**"));
	}

	/**
	 * [手機號碼] 前三位,後四位,其他隱藏<例子:138******1234>
	 * 
	 * @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), "*"), "***"));
	}

	/**
	 * [電話號碼] 以/分開 前三位,後四位,其他隱藏<例子:138******1234/****1234>
	 * 
	 * @param num
	 * @return
	 */
	public static String phone(String num) {
		if (StringUtils.isBlank(num)) {
			return "";
		}
		String[] split = num.split("/");
		StringBuffer sb = new StringBuffer();
		if (split.length > 1) {
			for (String number : split) {
				number = number.trim();
				number = caseNum(number);
				sb.append(number).append("/");
			}
			num = sb.toString();
			if (num.endsWith("/")) {
				num = num.substring(0, num.length() - 1);
			}
		} else {
			num = num.trim();
			num = caseNum(num);
		}
		return num;
	}

	private static String caseNum(String num) {
		switch (num.length()) {
		case 7:
			num = fixedPhone(num);
			break;
		case 8:
			num = fixedPhone(num);
			break;
		case 11:
			num = mobilePhone(num);
			break;
		default:
			break;
		}
		return num;
	}

	/**
	 * 資料長度大於12位,只顯示前面sensitiveSize位<例子:北京市海淀區****>
	 * 
	 * @param address
	 * @param sensitiveSize
	 *            敏感資訊長度
	 * @return
	 */
	private static String code_left(String address, int sensitiveSize) {
		if (StringUtils.isBlank(address)) {
			return "";
		}
		address=address.trim();
		return StringUtils.rightPad(StringUtils.left(address, sensitiveSize), StringUtils.length(address), "*");
	}

	/**
	 * 資料長度小於於12位,從後往前數sensitiveSize位設定為*<例子:廣州市******>
	 * 
	 * @param address
	 * @param sensitiveSize
	 *            敏感資訊長度
	 * @return
	 */
	private static String code_right_hide(String address, int sensitiveSize) {
		if (StringUtils.isBlank(address)) {
			return "";
		}
		int length = StringUtils.length(address);
		return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
	}

	/**
	 * 資料從後往前數sensitiveSize顯示<例子:***廣州市天河區>
	 * 
	 * @param address
	 * @param sensitiveSize
	 * @return
	 */
	@SuppressWarnings("unused")
	private static String code_right_display(String address, int sensitiveSize) {
		if (StringUtils.isBlank(address)) {
			return "";
		}
		String num = StringUtils.right(address, sensitiveSize);
		return StringUtils.leftPad(num, StringUtils.length(address), "*");
	}

	/**
	 * [地址] 如長度大於等於12位,留前6位,其餘為*,如少於12位,從後往前掩蓋6位為*
	 * 
	 * @param address
	 * @param sensitiveSize
	 *            敏感資訊長度
	 * @return
	 */
	public static String address(String address) {
		if (StringUtils.isBlank(address)) {
			return "";
		}
		int length = StringUtils.length(address);
		if (length >= 12) {
			return code_left(address, 6);
		} else {
			return code_right_hide(address, 6);
		}
	}

	/**
	 * [電子郵箱] 郵箱字首僅顯示第一個字母,字首其他隱藏,用星號代替,@及後面的地址顯示<例子:g**@163.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)));
	}

	/**
	 * [銀行卡號] 前六位,後四位,其他用星號隱藏每位1個星號<例子:6222600**********1234>
	 * 
	 * @param cardNum
	 * @return
	 */
	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), "*"), "******"));
	}

	/**
	 * [公司開戶銀行聯號] 公司開戶銀行聯行號,顯示前兩位,其他用星號隱藏,每位1個星號<例子:12********>
	 * 
	 * @param code
	 * @return
	 */
	public static String cnapsCode(String code) {
		if (StringUtils.isBlank(code)) {
			return "";
		}
		return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*");
	}

	/**
	 * [車牌號] 車牌號,顯示前4位,其他用星號隱藏,每位1個星號<例子:1222***>
	 * 
	 * @param code
	 * @return
	 */
	public static String plateNumber(String code) {
		if (StringUtils.isBlank(code)) {
			return "";
		}
		return StringUtils.rightPad(StringUtils.left(code, 4), StringUtils.length(code), "*");
	}

	/**
	 * [車輛識別號] 車輛識別號,從後往前數8位設定為*,其他用星號隱藏,每位1個星號<例子:1222********>
	 * 
	 * @param code
	 * @return
	 */
	public static String carCode(String code) {
		if (StringUtils.isBlank(code)) {
			return "";
		}
		return code_right_hide(code, 8);
	}

	/**
	 * [ 房源編號\土地稅源編號\土地使用證編號] 房源編號,留開頭3位,其餘為*<例子:122***>
	 * 
	 * @param code
	 * @return
	 */
	public static String resourceCode(String code) {
		if (StringUtils.isBlank(code)) {
			return "";
		}
		return StringUtils.rightPad(StringUtils.left(code, 3), StringUtils.length(code), "*");
	}

	/**
	 * 字串反轉
	 * 
	 * @param s
	 * @return
	 */
	@SuppressWarnings("unused")
	private static String reverseStringBuilder(String s) {
		StringBuilder sb = new StringBuilder(s);
		String afterreverse = sb.reverse().toString();
		return afterreverse;
	}

	/**
	 * 獲取脫敏json串 <注意:遞迴引用會導致java.lang.StackOverflowError>
	 * 
	 * @param javaBean
	 * @return
	 */
	public static String getJson(Object javaBean) {
		String json = null;
		if (null != javaBean) {
			Class<? extends Object> raw = javaBean.getClass();
			try {
				if (raw.isInterface())
					return json;
				Gson g = new Gson();
				Object clone = g.fromJson(g.toJson(javaBean, javaBean.getClass()), javaBean.getClass());
				Set<Integer> referenceCounter = new HashSet<Integer>();
				SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(raw), clone, referenceCounter);
				json = JSON.toJSONString(clone, SerializerFeature.WriteMapNullValue,
						SerializerFeature.WriteNullListAsEmpty);
				referenceCounter.clear();
				referenceCounter = null;
			} catch (Throwable e) {
				log.error("SensitiveInfoUtils.getJson() ERROR", e);
			}
		}
		return json;
	}

	private static Field[] findAllField(Class<?> clazz) {
		Field[] fileds = clazz.getDeclaredFields();
		while (null != clazz.getSuperclass() && !Object.class.equals(clazz.getSuperclass())) {
			fileds = (Field[]) ArrayUtils.addAll(fileds, clazz.getSuperclass().getDeclaredFields());
			clazz = clazz.getSuperclass();
		}
		return fileds;
	}

	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();
						// 1.處理子屬性,包括集合中的
						if (type.isArray()) {
							int len = Array.getLength(value);
							for (int i = 0; i < len; i++) {
								Object arrayObject = Array.get(value, i);
								SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(arrayObject.getClass()),
										arrayObject, referenceCounter);
							}
						} else if (value instanceof Collection<?>) {
							Collection<?> c = (Collection<?>) value;
							Iterator<?> it = c.iterator();
							while (it.hasNext()) {
								Object collectionObj = it.next();
								SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(collectionObj.getClass()),
										collectionObj, referenceCounter);
							}
						} else if (value instanceof Map<?, ?>) {
							Map<?, ?> m = (Map<?, ?>) value;
							Set<?> set = m.entrySet();
							for (Object o : set) {
								Entry<?, ?> entry = (Entry<?, ?>) o;
								Object mapVal = entry.getValue();
								SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(mapVal.getClass()), mapVal,
										referenceCounter);
							}
						} else if (!type.isPrimitive() && !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())) {
							SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(type), value, referenceCounter);
						}
					}
					// 2. 處理自身的屬性
					SensitiveInfo annotation = field.getAnnotation(SensitiveInfo.class);
					if (field.getType().equals(String.class) && null != annotation) {
						String valueStr = (String) value;
						if (StringUtils.isNotBlank(valueStr)) {
							switch (annotation.type()) {
							case CHINESE_NAME: {
								field.set(javaBean, SensitiveInfoUtils.chineseName(valueStr));
								break;
							}
							case ID_CARD: {
								field.set(javaBean, SensitiveInfoUtils.idCardNum(valueStr));
								break;
							}
							case TELE_PHONE: {
								field.set(javaBean, SensitiveInfoUtils.telePhone(valueStr));
								break;
							}
							case FIXED_PHONE: {
								field.set(javaBean, SensitiveInfoUtils.fixedPhone(valueStr));
								break;
							}
							case MOBILE_PHONE: {
								field.set(javaBean, SensitiveInfoUtils.mobilePhone(valueStr));
								break;
							}
							case PHONE: {
								field.set(javaBean, SensitiveInfoUtils.phone(valueStr));
								break;
							}
							case ADDRESS: {
								field.set(javaBean, SensitiveInfoUtils.address(valueStr));
								break;
							}
							case EMAIL: {
								field.set(javaBean, SensitiveInfoUtils.email(valueStr));
								break;
							}
							case BANK_CARD: {
								field.set(javaBean, SensitiveInfoUtils.bankCard(valueStr));
								break;
							}
							case CNAPS_CODE: {
								field.set(javaBean, SensitiveInfoUtils.cnapsCode(valueStr));
								break;
							}
							case PLATE_NUMBER: {
								field.set(javaBean, SensitiveInfoUtils.plateNumber(valueStr));
								break;
							}
							case CAR_CODE: {
								field.set(javaBean, SensitiveInfoUtils.carCode(valueStr));
								break;
							}
							case RESOURCE_CODE: {
								field.set(javaBean, SensitiveInfoUtils.resourceCode(valueStr));
								break;
							}
							}
						}
					}
				}
			}
		}
	}

	public static String mask(String code,String type){
		
		if (StringUtils.isNotBlank(code)&&StringUtils.isNotBlank(type)) {
			code = code.trim();
			switch (type) {
			case CHINESE_NAME: {
				code = SensitiveInfoUtils.chineseName(code);
				break;
			}
			case ID_CARD: {
				code = SensitiveInfoUtils.idCardNum(code);
				break;
			}
			case TELE_PHONE: {
				code = SensitiveInfoUtils.telePhone(code);
				break;
			}
			case FIXED_PHONE: {
				code =SensitiveInfoUtils.fixedPhone(code);
				break;
			}
			case MOBILE_PHONE: {
				code = SensitiveInfoUtils.mobilePhone(code);
				break;
			}
			case PHONE: {
				code = SensitiveInfoUtils.phone(code);
				break;
			}
			case ADDRESS: {
				code = SensitiveInfoUtils.address(code);
				break;
			}
			case EMAIL: {
				code =SensitiveInfoUtils.email(code);
				break;
			}
			case BANK_CARD: {
				code =SensitiveInfoUtils.bankCard(code);
				break;
			}
			case CNAPS_CODE: {
				code =SensitiveInfoUtils.cnapsCode(code);
				break;
			}
			case PLATE_NUMBER: {
				code = SensitiveInfoUtils.plateNumber(code);
				break;
			}
			case CAR_CODE: {
				code =SensitiveInfoUtils.carCode(code);
				break;
			}
			case RESOURCE_CODE: {
				code =SensitiveInfoUtils.resourceCode(code);
				break;
			}
			}
		}
		
		return code;
	}
	
	// ----------------------------------------------------------------------------------------------
	public static Method[] findAllMethod(Class<?> clazz) {
		Method[] methods = clazz.getMethods();
		return methods;
	}

	// ----------------------------------------------------------------------------------------------
	public static enum SensitiveType {
		/**
		 * 中文名
		 */
		CHINESE_NAME,

		/**
		 * 身份證號
		 */
		ID_CARD,
		/**
		 * 座機號
		 */
		TELE_PHONE,
		/**
		 * 固定電話
		 */
		FIXED_PHONE,
		/**
		 * 手機號
		 */
		MOBILE_PHONE,
		/**
		 * 電話號碼(包括手機號和固定電話)
		 */
		PHONE,
		/**
		 * 地址
		 */
		ADDRESS,
		/**
		 * 電子郵件
		 */
		EMAIL,
		/**
		 * 銀行卡
		 */
		BANK_CARD,
		/**
		 * 公司開戶銀行聯號
		 */
		CNAPS_CODE,
		/**
		 * 車輛識別號
		 */
		CAR_CODE,
		/**
		 * 房源編號\土地稅源編號\土地使用證編號
		 */
		RESOURCE_CODE,
		/**
		 * 車牌號
		 */
		PLATE_NUMBER;
	}
}
x 649   1
package
com.foresee.zxpt.common.mask;
2
3
import java.lang.reflect.Array;
4
import
java.lang.reflect.Field;
5
import java.lang.reflect.Method;
6
import java.util.Collection;
7
import java.util.HashSet;
8
import java.util.Iterator;
9
import java.util.Map;
10
import java.util.Map.Entry;
11
import java.util.Set;
12
13
import org.apache.commons.lang3.ArrayUtils;
14
import org.apache.commons.lang3.StringUtils;
15
16
import com.alibaba.fastjson.JSON;
17
import com.alibaba.fastjson.serializer.SerializerFeature;
18
import com.google.gson.Gson;
19
20
import lombok.extern.slf4j.Slf4j;
21
22
/**
23
 * 資料脫敏處理工具類
24
 * @version 1.0
25
 * @date 2018年9月18日下午5:23:05
26
 */
27
@Slf4j
28
public class SensitiveInfoUtils {
29
30
    /**
31
     * 中文名
32
     */
33
    public static final String CHINESE_NAME="01";
34
35
    /**
36
     * 身份證號
37
     */
38
    public static final String ID_CARD="02";
39
    /**
40
     * 座機號
41
     */
42
    public static final String TELE_PHONE="03";
43
    /**
44
     * 固定電話
45
     */
46
    public static final String FIXED_PHONE="04";
47
    /**
48
     * 手機號
49
     */
50
    public static final String MOBILE_PHONE="05";
51
    /**
52
     * 電話號碼(包括手機號和固定電話)
53
     */
54
    public static final String PHONE="06";
55
    /**
56
     * 地址
57
     */
58
    public static final String ADDRESS="07";
59
    /**
60
     * 電子郵件
61
     */
62
    public static final String EMAIL="08";
63
    /**
64
     * 銀行卡
65
     */
66
    public static final String BANK_CARD="09";
67
    /**
68
     * 公司開戶銀行聯號
69
     */
70
    public static final String CNAPS_CODE="10";
71
    /**
72
     * 車輛識別號
73
     */
74
    public static final String CAR_CODE="11";
75
    /**
76
     * 房源編號\土地稅源編號\土地使用證編號
77
     */
78
    public static final String RESOURCE_CODE="12";
79
    /**
80
     * 車牌號
81
     */
82
    public static final String PLATE_NUMBER="13";
83
84
    /**
85
     * [中文姓名] 只顯示第一個漢字,其他隱藏為2個星號<例子:李**>
86
     * 
87
     * @param name
88
     * @return
89
     */
90
    public static String chineseName(String fullName) {
91
        if (StringUtils.isBlank(fullName)) {
92
            return "";
93
        }
94
        String name = StringUtils.left(fullName, 1);
95
        return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
96
    }
97
98
    /**
99
     * [中文姓名] 只顯示第一個漢字,其他隱藏為2個星號<例子:李**>
100
     * 
101
     * @param familyName
102