思路:如果我有一个复杂的对象,那么这个对象每个属性的值,我肯定是已知的,而且它的字段类型是已知的,字段的返回值是已知的,对象的类注解,字段的注解,方法的注解我都能拿到(利用反射)那么问题是不是就变的简单很多呢?
因为我可以利用注解,在我想要实现脱敏的字段上加上指定注解,然后最后拿到的value,利用反射给他set回去,那么这样是不是就实现了呢?下面看代码如何实现的!
代码:
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Desensitized {
/*脱敏类型(规则)*/
SensitiveTypeEnum type();
/*判断注解是否生效的方法*/
String isEffictiveMethod() default "";
}
package com.danny.log.desensitized.entity;
import com.danny.log.desensitized.annotation.Desensitized;
import com.danny.log.desensitized.enums.SensitiveTypeEnum;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author [email protected]
* @Title: BaseUserInfo
* @Copyright: Copyright (c) 2016
* @Description:
* @Company: lxjr.com
* @Created on 2017-06-07 15:19:23
*/
public class BaseUserInfo extends BaseEntity{
private List<Map> mapList;
private List<String> strList;
private Map<String,UserTypeEnum> map;
private List<UserService> userServiceList;
private ILimitKey iLimitKey;
private UserTypeEnum userType;
private static final long serialVersionUID = -3387516993124229938L;
private UserService userService;
@Desensitized(type = SensitiveTypeEnum.CHINESE_NAME)
private String realName;
@Desensitized(type = SensitiveTypeEnum.ID_CARD)
private String idCardNo;
@Desensitized(type = SensitiveTypeEnum.MOBILE_PHONE)
private String mobileNo;
private String account;
@Desensitized(type = SensitiveTypeEnum.PASSWORD, isEffictiveMethod = "isEffictiveMethod")
private String password;
@Desensitized(type = SensitiveTypeEnum.BANK_CARD)
private String bankCardNo;
@Desensitized(type = SensitiveTypeEnum.EMAIL)
private String email;
private String extend1;
private Integer extend2;
private BigDecimal extend3;
private Date extend4;
public UserService getUserService() {
return userService;
}
public BaseUserInfo setUserService(UserService userService) {
this.userService = userService;
return this;
}
public UserTypeEnum getUserType() {
return userType;
}
public BaseUserInfo setUserType(UserTypeEnum userType) {
this.userType = userType;
return this;
}
public String getRealName() {
return realName;
}
public BaseUserInfo setRealName(String realName) {
this.realName = realName;
return this;
}
public String getIdCardNo() {
return idCardNo;
}
public BaseUserInfo setIdCardNo(String idCardNo) {
this.idCardNo = idCardNo;
return this;
}
public String getMobileNo() {
return mobileNo;
}
public BaseUserInfo setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
return this;
}
public String getAccount() {
return account;
}
public BaseUserInfo setAccount(String account) {
this.account = account;
return this;
}
public String getPassword() {
return password;
}
public BaseUserInfo setPassword(String password) {
this.password = password;
return this;
}
public String getBankCardNo() {
return bankCardNo;
}
public BaseUserInfo setBankCardNo(String bankCardNo) {
this.bankCardNo = bankCardNo;
return this;
}
public String getEmail() {
return email;
}
public BaseUserInfo setEmail(String email) {
this.email = email;
return this;
}
public String getExtend1() {
return extend1;
}
public BaseUserInfo setExtend1(String extend1) {
this.extend1 = extend1;
return this;
}
public Integer getExtend2() {
return extend2;
}
public BaseUserInfo setExtend2(Integer extend2) {
this.extend2 = extend2;
return this;
}
public BigDecimal getExtend3() {
return extend3;
}
public BaseUserInfo setExtend3(BigDecimal extend3) {
this.extend3 = extend3;
return this;
}
public Date getExtend4() {
return extend4;
}
public BaseUserInfo setExtend4(Date extend4) {
this.extend4 = extend4;
return this;
}
public List<String> getStrList() {
return strList;
}
public BaseUserInfo setStrList(List<String> strList) {
this.strList = strList;
return this;
}
public Map<String, UserTypeEnum> getMap() {
return map;
}
public BaseUserInfo setMap(Map<String, UserTypeEnum> map) {
this.map = map;
return this;
}
public ILimitKey getiLimitKey() {
return iLimitKey;
}
public BaseUserInfo setiLimitKey(ILimitKey iLimitKey) {
this.iLimitKey = iLimitKey;
return this;
}
public List<UserService> getUserServiceList() {
return userServiceList;
}
public BaseUserInfo setUserServiceList(List<UserService> userServiceList) {
this.userServiceList = userServiceList;
return this;
}
public List<Map> getMapList() {
return mapList;
}
public BaseUserInfo setMapList(List<Map> mapList) {
this.mapList = mapList;
return this;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
/**
* 如果账号等于"dannyhoo1234561"时,密码字段脱敏生效
*
* @return
*/
public boolean isEffictiveMethod() {
boolean isEffictive = "dannyhoo123456".equals(getAccount());
return isEffictive;
}
}
@Test
public void testUserInfo() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
List<String> stringList = new ArrayList<String>();
stringList.add("danny");
stringList.add("hoo");
stringList.add("song");
Map<String,UserTypeEnum> map=new HashMap<String, UserTypeEnum>();
map.put("dannymap",UserTypeEnum.ADMINISTRATOR);
Map<String,UserTypeEnum> map1=new HashMap<String, UserTypeEnum>();
map1.put("dannymap",UserTypeEnum.GENERAL);
Map<String,UserTypeEnum> map2=new HashMap<String, UserTypeEnum>();
map2.put("dannymap",UserTypeEnum.OPERATOR);
List<Map> mapList= new ArrayList<>();
mapList.add(map1);
mapList.add(map2);
mapList.add(map);
/*单个实体*/
BaseUserInfo baseUserInfo = new BaseUserInfo()
.setRealName("胡丹尼")
.setIdCardNo("158199199013141120")
.setMobileNo("13579246810")
.setAccount("dannyhoo123456")
.setPassword("123456")
.setBankCardNo("6227000212090659057")
.setEmail("[email protected]")
.setUserType(UserTypeEnum.ADMINISTRATOR)
.setUserService(new UserServiceImpl())
.setStrList(stringList)
.setMap(map)
.setiLimitKey(LimitFrequencyKeyEnum.SMSCODE_MOBILE_DAY_LIMIT)
.setMapList(mapList);
/*父类属性*/
baseUserInfo.setId(101202L)
.setCreateTime(new Date())
.setUpdateTime(new Date());
/*嵌套实体*/
UserPackage userPackage = new UserPackage()
.setFlag(true)
.setBaseUserInfo(baseUserInfo)
.setUserPackageName("UserPackageName_Danny");
System.out.println("脱敏前:" + JSON.toJSONString(baseUserInfo));
System.out.println("脱敏后:" + DesensitizedUtils.getJson(baseUserInfo));
System.out.println("嵌套实体脱敏后:" + DesensitizedUtils.getJson(userPackage));
}
public static String getJson(Object javaBean) {
String json = null;
if (null != javaBean) {
try {
if (javaBean.getClass().isInterface()) return json;
/* 克隆出一个实体进行字段修改,避免修改原实体 */
// Object clone =ObjectUtils.deepCloneObject(javaBean);
// Object clone =ObjectUtils.deepCloneByFastJson(javaBean);
// Object clone = ObjectUtils.deepClone(javaBean);
Object clone = ObjectUtils.MydeepClone(javaBean);
// System.out.println("clone:"+JSON.toJSONString(clone));
/* 定义一个计数器,用于避免重复循环自定义对象类型的字段 */
Set<Integer> referenceCounter = new HashSet<Integer>();
/* 对克隆实体进行脱敏操作 */
DesensitizedUtils.replace(ObjectUtils.getAllFields(clone), clone, referenceCounter);
/* 利用fastjson对脱敏后的克隆对象进行序列化 */
json = JSON.toJSONString(clone, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty);
/* 清空计数器 */
referenceCounter.clear();
referenceCounter = null;
} catch (Throwable e) {
e.printStackTrace();
}
}
return json;
}
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(ObjectUtils.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(ObjectUtils.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(ObjectUtils.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(ObjectUtils.getAllFields(value), value, referenceCounter);
}
}
}
//脱敏操作
setNewValueForField(javaBean, field, value);
}
}
}
}
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, 8));
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;
}
}
}
}
}