基于实体的注解
先定义一个基于对象的脱敏注解
/**
* 属性脱敏注解
*
* @author kandw [kandw@yinhai.com]
* @version 2019/8/28
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TaSensitive {
/**
* 返回脱敏字段是否带加密文本,若是设置为true,则和返回脱敏文本时同时返回本字段的RSA加密字段
*
* @return
*/
boolean withEncrypt() default false;
/**
* 前缀预留位数
* 比如:
* prefixLength=3
* private String idCard="41234560987123543"
* 打码后为: idCard= 412**************
*/
int prefixLength() default 0;
/**
* 后缀预留位数
* 比如:
* suffixLength=3
* private String idCard="41234560987123543"
* 打码后为: idCard= **************543
*/
int suffixLength() default 0;
/**
* 敏感字符替换字符
* 比如: sensitiveChar="$",(suffixLength=3);
*/
String sensitiveChar() default "*";
}
脱敏注解实现
/**
* 数据脱敏工具
*
* @author kandw [kandw@yinhai.com]
* @version 2019/8/28
*/
public class DesensitizeUtil {
private DesensitizeUtil() {
//empty internal constructor
}
/**
* List<object> 打码
*
* @param obj 需要脱敏问List集合
* @return 返回脱敏后的数据
*/
public static List<Object> maskListObject(List<Object> obj) {
if (null == obj || obj.isEmpty()) {
return Collections.emptyList();
}
List<Object> maskList = new ArrayList<>();
for (Object e : obj) {
maskObject(e);
maskList.add(e);
}
return maskList;
}
@SuppressWarnings("unchecked")
public static <E> E mask(E obj) {
if (obj instanceof Collection) {
((Collection) obj).forEach(DesensitizeUtil::maskObject);
} else {
obj = maskObject(obj);
}
return obj;
}
/**
* 字符串脱敏
*
* @param obj 需要脱敏的对象
* @return 返回脱敏后的对象
*/
public static <E> E maskObject(E obj) {
if (null == obj) {
return null;
}
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
TaSensitive annotation = field.getAnnotation(TaSensitive.class);
//只能对字符串脱敏
if (null == annotation || !field.getType().equals(String.class)) {
continue;
}
String value = null;
try {
value = (String) field.get(obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (StringUtils.isEmpty(value)) {
continue;
}
int suffix = annotation.suffixLength();
int prefix = annotation.prefixLength();
String character = annotation.sensitiveChar();
try {
String sensitiveStr = maskString(value, character, prefix,
suffix);
//此处如果不需要可注释
//if (annotation.withEncrypt()) {
field.set(obj, JsonFactory.bean2json(new TaSensitiveBean(sensitiveStr, RSAUtils.encryptWidthEncode(value), new Format(prefix, suffix))));
//} else {
field.set(obj, sensitiveStr);
//}
} catch (IllegalAccessException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return obj;
}
/**
* 对字符串脱敏
*
* @param content 需要脱敏的正文
* @param character 脱敏后字符
* @param prefix 预留前缀(不需要脱敏的)
* @param suffix 预留后缀(不需要脱敏的)
* @return 脱敏后的正文
*/
@PostMapping
public static String maskString(String content, String character, int prefix, int suffix) {
if (StringUtils.isEmpty(content)) {
return "";
}
String replacement = produceCharacter(content.length() - prefix - suffix, character);
String regex = "([\\s\\S]{" + prefix + "})([\\s\\S]+)([\\s\\S]{" + suffix + "})";
//*的数量是content.length -start-end
return content.replaceAll(regex, "$1" + replacement + "$3");
}
private static String produceCharacter(int len, String character) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
sb.append(character);
}
return sb.toString();
}
}
基于接口的注解
基于接口调用待补充