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
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
* @param givenName
103
* @return
104
*/
105
public static String chineseName(String familyName, String givenName) {
106
if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) {
107
return "";
108
}
109
return chineseName(familyName + givenName);
110
}
111
112
/**
113
* [身份证号] 显示前6后2,其他隐藏。共计18位或者15位。<例子:*************5762>
114
*
115
* @param id
116
* @return
117
*/
118
public static String idCardNum(String id) {
119
if (StringUtils.isBlank(id)) {
120
return "";
121
}
122
return StringUtils.left(id, 6).concat(StringUtils
123
.removeStart(StringUtils.leftPad(StringUtils.right(id, 2), StringUtils.length(id), "*"), "******"));
124
}
125
126
/**
127
* [固定电话] 后四位,其他隐藏<例子:****1234>
128
*
129
* @param num
130
* @return
131
*/
132
public static String telePhone(String num) {
133
if (StringUtils.isBlank(num)) {
134
return "";
135
}
136
return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
137
}
138
139
/**
140
* [固定电话] 前两位,后两位,其他隐藏<例子:88**34>
141
*
142
* @param num
143
* @return
144
*/
145
public static String fixedPhone(String num) {
146
if (StringUtils.isBlank(num)) {
147
return "";
148
}
149
return StringUtils.left(num, 2).concat(StringUtils
150
.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "**"));
151
}
152
153
/**
154
* [手机号码] 前三位,后四位,其他隐藏<例子:138******1234>
155
*
156
* @param num
157
* @return
158
*/
159
public static String mobilePhone(String num) {
160
if (StringUtils.isBlank(num)) {
161
return "";
162
}
163
return StringUtils.left(num, 3).concat(StringUtils
164
.removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), "***"));
165
}
166
167
/**
168
* [电话号码] 以/分开 前三位,后四位,其他隐藏<例子:138******1234/****1234>
169
*
170
* @param num
171
* @return
172
*/
173
public static String phone(String num) {
174
if (StringUtils.isBlank(num)) {
175
return "";
176
}
177
String[] split = num.split("/");
178
StringBuffer sb = new StringBuffer();
179
if (split.length > 1) {
180
for (String number : split) {
181
number = number.trim();
182
number = caseNum(number);
183
sb.append(number).append("/");
184
}
185
num = sb.toString();
186
if (num.endsWith("/")) {
187
num = num.substring(0, num.length() - 1);
188
}
189
} else {
190
num = num.trim();
191
num = caseNum(num);
192
}
193
return num;
194
}
195
196
private static String caseNum(String num) {
197
switch (num.length()) {
198
case 7:
199
num = fixedPhone(num);
200
break;
201
case 8:
202
num = fixedPhone(num);
203
break;
204
case 11:
205
num = mobilePhone(num);
206
break;
207
default:
208
break;
209
}
210
return num;
211
}
212
213
/**
214
* 数据长度大于12位,只显示前面sensitiveSize位<例子:北京市海淀区****>
215
*
216
* @param address
217
* @param sensitiveSize
218
* 敏感信息长度
219
* @return
220
*/
221
private static String code_left(String address, int sensitiveSize) {
222
if (StringUtils.isBlank(address)) {
223
return "";
224
}
225
address=address.trim();
226
return StringUtils.rightPad(StringUtils.left(address, sensitiveSize), StringUtils.length(address), "*");
227
}
228
229
/**
230
* 数据长度小于于12位,从后往前数sensitiveSize位设置为*<例子:广州市******>
231
*
232
* @param address
233
* @param sensitiveSize
234
* 敏感信息长度
235
* @return
236
*/
237
private static String code_right_hide(String address, int sensitiveSize) {
238
if (StringUtils.isBlank(address)) {
239
return "";
240
}
241
int length = StringUtils.length(address);
242
return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
243
}
244
245
/**
246
* 数据从后往前数sensitiveSize显示<例子:***广州市天河区>
247
*
248
* @param address
249
* @param sensitiveSize
250
* @return
251
*/
252
("unused")
253
private static String code_right_display(String address, int sensitiveSize) {
254
if (StringUtils.isBlank(address)) {
255
return "";
256
}
257
String num = StringUtils.right(address, sensitiveSize);
258
return StringUtils.leftPad(num, StringUtils.length(address), "*");
259
}
260
261
/**
262
* [地址] 如长度大于等于12位,留前6位,其余为*,如少于12位,从后往前掩盖6位为*
263
*
264
* @param address
265
* @param sensitiveSize
266
* 敏感信息长度
267
* @return
268
*/
269
public static String address(String address) {
270
if (StringUtils.isBlank(address)) {
271
return "";
272
}
273
int length = StringUtils.length(address);
274
if (length >= 12) {
275
return code_left(address, 6);
276
} else {
277
return code_right_hide(address, 6);
278
}
279
}
280
281
/**
282
* [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com>
283
*
284
* @param email
285
* @return
286
*/
287
public static String email(String email) {
288
if (StringUtils.isBlank(email)) {
289
return "";
290
}
291
int index = StringUtils.indexOf(email, "@");
292
if (index <= 1)
293
return email;
294
else
295
return StringUtils.rightPad(StringUtils.left(email, 1), index, "*")
296
.concat(StringUtils.mid(email, index, StringUtils.length(email)));
297
}
298
299
/**
300
* [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234>
301
*
302
* @param cardNum
303
* @return
304
*/
305
public static String bankCard(String cardNum) {
306
if (StringUtils.isBlank(cardNum)) {
307
return "";
308
}
309
return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(
310
StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
311
}
312
313
/**
314
* [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********>
315
*
316
* @param code
317
* @return
318
*/
319
public static String cnapsCode(String code) {
320
if (StringUtils.isBlank(code)) {
321
return "";
322
}
323
return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*");
324
}
325
326
/**
327
* [车牌号] 车牌号,显示前4位,其他用星号隐藏,每位1个星号<例子:1222***>
328
*
329
* @param code
330
* @return
331
*/
332
public static String plateNumber(String code) {
333
if (StringUtils.isBlank(code)) {
334
return "";
335
}
336
return StringUtils.rightPad(StringUtils.left(code, 4), StringUtils.length(code), "*");
337
}
338
339
/**
340
* [车辆识别号] 车辆识别号,从后往前数8位设置为*,其他用星号隐藏,每位1个星号<例子:1222********>
341
*
342
* @param code
343
* @return
344
*/
345
public static String carCode(String code) {
346
if (StringUtils.isBlank(code)) {
347
return "";
348
}
349
return code_right_hide(code, 8);
350
}
351
352
/**
353
* [ 房源编号\土地税源编号\土地使用证编号] 房源编号,留开头3位,其余为*<例子:122***>
354
*
355
* @param code
356
* @return
357
*/
358
public static String resourceCode(String code) {
359
if (StringUtils.isBlank(code)) {
360
return "";
361
}
362
return StringUtils.rightPad(StringUtils.left(code, 3), StringUtils.length(code), "*");
363
}
364
365
/**
366
* 字符串反转
367
*
368
* @param s
369
* @return
370
*/
371
("unused")
372
private static String reverseStringBuilder(String s) {
373
StringBuilder sb = new StringBuilder(s);
374
String afterreverse = sb.reverse().toString();
375
return afterreverse;
376
}
377
378
/**
379
* 获取脱敏json串 <注意:递归引用会导致java.lang.StackOverflowError>
380
*
381
* @param javaBean
382
* @return
383
*/
384
public static String getJson(Object javaBean) {
385
String json = null;
386
if (null != javaBean) {
387
Class<? extends Object> raw = javaBean.getClass();
388
try {
389
if (raw.isInterface())
390
return json;
391
Gson g = new Gson();
392
Object clone = g.fromJson(g.toJson(javaBean, javaBean.getClass()), javaBean.getClass());
393
Set<Integer> referenceCounter = new HashSet<Integer>();
394
SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(raw), clone, referenceCounter);
395
json = JSON.toJSONString(clone, SerializerFeature.WriteMapNullValue,
396
SerializerFeature.WriteNullListAsEmpty);
397
referenceCounter.clear();
398
referenceCounter = null;
399
} catch (Throwable e) {
400
log.error("SensitiveInfoUtils.getJson() ERROR", e);
401
}
402
}
403
return json;
404
}
405
406
private static Field[] findAllField(Class<?> clazz) {
407
Field[] fileds = clazz.getDeclaredFields();
408
while (null != clazz.getSuperclass() && !Object.class.equals(clazz.getSuperclass())) {
409
fileds = (Field[]) ArrayUtils.addAll(fileds, clazz.getSuperclass().getDeclaredFields());
410
clazz = clazz.getSuperclass();
411
}
412
return fileds;
413
}
414
415
private static void replace(Field[] fields, Object javaBean, Set<Integer> referenceCounter)
416
throws IllegalArgumentException, IllegalAccessException {
417
if (null != fields && fields.length > 0) {
418
for (Field field : fields) {
419
field.setAccessible(true);
420
if (null != field && null != javaBean) {
421
Object value = field.get(javaBean);
422
if (null != value) {
423
Class<?> type = value.getClass();
424
// 1.处理子属性,包括集合中的
425
if (type.isArray()) {
426
int len = Array.getLength(value);
427
for (int i = 0; i < len; i++) {
428
Object arrayObject = Array.get(value, i);
429
SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(arrayObject.getClass()),
430
arrayObject, referenceCounter);
431
}
432
} else if (value instanceof Collection<?>) {
433
Collection<?> c = (Collection<?>) value;
434
Iterator<?> it = c.iterator();
435
while (it.hasNext()) {
436
Object collectionObj = it.next();
437
SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(collectionObj.getClass()),
438
collectionObj, referenceCounter);
439
}
440
} else if (value instanceof Map<?, ?>) {
441
Map<?, ?> m = (Map<?, ?>) value;
442
Set<?> set = m.entrySet();
443
for (Object o : set) {
444
Entry<?, ?> entry = (Entry<?, ?>) o;
445
Object mapVal = entry.getValue();
446
SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(mapVal.getClass()), mapVal,
447
referenceCounter);
448
}
449
} else if (!type.isPrimitive() && !StringUtils.startsWith(type.getPackage().getName(), "javax.")
450
&& !StringUtils.startsWith(type.getPackage().getName(), "java.")
451
&& !StringUtils.startsWith(field.getType().getName(), "javax.")
452
&& !StringUtils.startsWith(field.getName(), "java.")
453
&& referenceCounter.add(value.hashCode())) {
454
SensitiveInfoUtils.replace(SensitiveInfoUtils.findAllField(type), value, referenceCounter);
455
}
456
}
457
// 2. 处理自身的属性
458
SensitiveInfo annotation = field.getAnnotation(SensitiveInfo.class);
459
if (field.getType().equals(String.class) && null != annotation) {
460
String valueStr = (String) value;
461
if (StringUtils.isNotBlank(valueStr)) {
462
switch (annotation.type()) {
463
case CHINESE_NAME: {
464
field.set(javaBean, SensitiveInfoUtils.chineseName(valueStr));
465
break;
466
}
467
case ID_CARD: {
468
field.set(javaBean, SensitiveInfoUtils.idCardNum(valueStr));
469
break;
470
}
471
case TELE_PHONE: {
472
field.set(javaBean, SensitiveInfoUtils.telePhone(valueStr));
473
break;
474
}
475
case FIXED_PHONE: {
476
field.set(javaBean, SensitiveInfoUtils.fixedPhone(valueStr));
477
break;
478
}
479
case MOBILE_PHONE: {
480
field.set(javaBean, SensitiveInfoUtils.mobilePhone(valueStr));
481
break;
482
}
483
case PHONE: {
484
field.set(javaBean, SensitiveInfoUtils.phone(valueStr));
485
break;
486
}
487
case ADDRESS: {
488
field.set(javaBean, SensitiveInfoUtils.address(valueStr));
489
break;
490
}
491
case EMAIL: {
492
field.set(javaBean, SensitiveInfoUtils.email(valueStr));
493
break;
494
}
495
case BANK_CARD: {
496
field.set(javaBean, SensitiveInfoUtils.bankCard(valueStr));
497
break;
498
}
499
case CNAPS_CODE: {
500
field.set(javaBean, SensitiveInfoUtils.cnapsCode(valueStr));
501
break;
502
}
503
case PLATE_NUMBER: {
504
field.set(javaBean, SensitiveInfoUtils.plateNumber(valueStr));
505
break;
506
}
507
case CAR_CODE: {
508
field.set(javaBean, SensitiveInfoUtils.carCode(valueStr));
509
break;
510
}
511
case RESOURCE_CODE: {
512
field.set(javaBean, SensitiveInfoUtils.resourceCode(valueStr));
513
break;
514
}
515
}
516
}
517
}
518
}
519
}
520
}
521
}
522
523
public static String mask(String code,String type){
524
525
if (StringUtils.isNotBlank(code)&&StringUtils.isNotBlank(type)) {
526
code = code.trim();
527
switch (type) {
528
case CHINESE_NAME: {
529
code = SensitiveInfoUtils.chineseName(code);
530
break;
531
}
532
case ID_CARD: {
533
code = SensitiveInfoUtils.idCardNum(code);
534
break;
535
}
536
case TELE_PHONE: {
537
code = SensitiveInfoUtils.telePhone(code);
538
break;
539
}
540
case FIXED_PHONE: {
541
code =SensitiveInfoUtils.fixedPhone(code);
542
break;
543
}
544
case MOBILE_PHONE: {
545
code = SensitiveInfoUtils.mobilePhone(code);
546
break;
547
}
548
case PHONE: {
549
code = SensitiveInfoUtils.phone(code);
550
break;
551
}
552
case ADDRESS: {
553
code = SensitiveInfoUtils.address(code);
554
break;
555
}
556
case EMAIL: {
557
code =SensitiveInfoUtils.email(code);
558
break;
559
}
560
case BANK_CARD: {
561
code =SensitiveInfoUtils.bankCard(code);
562
break;
563
}
564
case CNAPS_CODE: {
565
code =SensitiveInfoUtils.cnapsCode(code);
566
break;
567
}
568
case PLATE_NUMBER: {
569
code = SensitiveInfoUtils.plateNumber(code);
570
break;
571
}
572
case CAR_CODE: {
573
code =SensitiveInfoUtils.carCode(code);
574
break;
575
}
576
case RESOURCE_CODE: {
577
code =SensitiveInfoUtils.resourceCode(code);
578
break;
579
}
580
}
581
}
582
583
return code;
584
}
585
586
// ----------------------------------------------------------------------------------------------
587
public static Method[] findAllMethod(Class<?> clazz) {
588
Method[] methods = clazz.getMethods();
589
return methods;
590
}
591
592
// ----------------------------------------------------------------------------------------------
593
public static enum SensitiveType {
594
/**
595
* 中文名
596
*/
597
CHINESE_NAME,
598
599
/**
600
* 身份证号
601
*/
602
ID_CARD,
603
/**
604
* 座机号
605
*/
606
TELE_PHONE,
607
/**
608
* 固定电话
609
*/
610
FIXED_PHONE,
611
/**
612
* 手机号
613
*/
614
MOBILE_PHONE,
615
/**
616
* 电话号码(包括手机号和固定电话)
617
*/
618
PHONE,
619
/**
620
* 地址
621
*/
622
ADDRESS,
623
/**
624
* 电子邮件
625
*/
626
EMAIL,
627
/**
628
* 银行卡
629
*/
630
BANK_CARD,
631
/**
632
* 公司开户银行联号
633
*/
634
CNAPS_CODE,
635
/**
636
* 车辆识别号
637
*/
638
CAR_CODE,
639
/**
640
* 房源编号\土地税源编号\土地使用证编号
641
*/
642
RESOURCE_CODE,
643
/**
644
* 车牌号
645
*/
646
PLATE_NUMBER;
647
}
648
}
649
package com.foresee.zxpt.common.mask;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface SensitiveInfo {
public SensitiveInfoUtils.SensitiveType type() ;
}
1
17
1
package com.foresee.zxpt.common.mask;
2
3
import java.lang.annotation.Documented;
4
import java.lang.annotation.ElementType;
5
import java.lang.annotation.Inherited;
6
import java.lang.annotation.Retention;
7
import java.lang.annotation.RetentionPolicy;
8
import java.lang.annotation.Target;
9
10
ElementType.FIELD,ElementType.METHOD}) ({
11
RetentionPolicy.RUNTIME) (
12
13
14
public @interface SensitiveInfo {
15
16
public SensitiveInfoUtils.SensitiveType type() ;
17
}
package com.foresee.common.mask;
import com.foresee.common.mask.SensitiveInfoUtils.SensitiveType;
import lombok.Data;
public class Test {
public static void main(String[] args) {
// String num="13257917009/8888888";
// String phone = SensitiveInfoUtils.phone(num);
// System.out.println(phone);
User user =new Test().new User();
user.setAddress("广东省广州市天河区鸡山村");
user.setIdCard("362228199208142414");
user.setPhone("13257917009/12345678");
user.setResource("1234567890");
String json = SensitiveInfoUtils.getJson(user);
System.out.println(json);
}
@Data
class User{
@SensitiveInfo(type=SensitiveType.PHONE)
String phone;
@SensitiveInfo(type=SensitiveType.ADDRESS)
String address;
@SensitiveInfo(type=SensitiveType.RESOURCE_CODE)
String resource;
@SensitiveInfo(type=SensitiveType.ID_CARD)
String idCard;
}
}
1
34
1
package com.foresee.common.mask;
2
3
import com.foresee.common.mask.SensitiveInfoUtils.SensitiveType;
4
5
import lombok.Data;
6
7
public class Test {
8
9
public static void main(String[] args) {
10
// String num="13257917009/8888888";
11
// String phone = SensitiveInfoUtils.phone(num);
12
// System.out.println(phone);
13
User user =new Test().new User();
14
user.setAddress("广东省广州市天河区鸡山村");
15
user.setIdCard("362228199208142414");
16
user.setPhone("13257917009/12345678");
17
user.setResource("1234567890");
18
String json = SensitiveInfoUtils.getJson(user);
19
System.out.println(json);
20
}
21
22
23
class User{
24
(type=SensitiveType.PHONE)
25
String phone;
26
(type=SensitiveType.ADDRESS)
27
String address;
28
(type=SensitiveType.RESOURCE_CODE)
29
String resource;
30
(type=SensitiveType.ID_CARD)
31
String idCard;
32
}
33
}
34