如何实现一个复杂对象的部分字段脱敏操作

思路:如果我有一个复杂的对象,那么这个对象每个属性的值,我肯定是已知的,而且它的字段类型是已知的,字段的返回值是已知的,对象的类注解,字段的注解,方法的注解我都能拿到(利用反射)那么问题是不是就变的简单很多呢?
因为我可以利用注解,在我想要实现脱敏的字段上加上指定注解,然后最后拿到的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;
                    }
                }
            }
        }
    }

你可能感兴趣的:(java,开发语言,后端)