自定义注解给属性加密

1、创建注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface EncryptionSM4 {
//可以给个默认值,然后根据不同的值采用不同加密方式
//String type() default "SM4";
}

2、在属性上加入注解

需要加密的字段

//三个实例类注意
//请求报文
@Data
public class FallbackRequestModel implements Serializable {
    /**
     * 交易流水号
     */
    @NotBlank(message = "tradeNo必填!")
    private String tradeNo;
    /**
     * 服务接口公共入参
     */
    @NotNull(message = "common必填!")
    private CommonModel common;
}

@Data
public class CommonModel implements Serializable {
    @NotEmpty(message = "people不能为空!")
    private List<PeopleModel> people;
}

@Data
public class PeopleModel implements Serializable {
    @NotBlank(message = "idNumber不能为空!")
    @EncryptionSM4
    private String idNumber;
}

请求报文示例:

{
     "tradeNo":"12345",
     "common": { 
        "people": [{
                "idNumber": "852741963852741" 
            },
            {
             
                "idNumber": "1234567987984891"
            }
        ]
    }
}

我们需要给每个人的证件号加密,这些people是一个list集合

3、 编写方法,解析注解

 private void encrypt(Object obj) throws Exception{
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            if(!field.isAccessible()){
                //赋权使用,否则private类型是无法操作的
                field.setAccessible(true);
            }
            //判断是否为list
            if(List.class.isAssignableFrom(field.getType())){
                Type t = field.getGenericType();
                if(t instanceof ParameterizedType){
                    //获取对象list属性的class
                    Class clazz = field.get(obj).getClass();
                    //获取list属性的size方法
                    Method m = clazz.getDeclaredMethod("size");
                    //调用size方法
                    int  size = (Integer)m.invoke(field.get(obj));
                    //根据size大小循环
                    for(int i = 0; i < size; i++){
                        //获取list属性的get方法
                        Method getM = clazz.getDeclaredMethod("get", int.class);
                        //调用get方法获取list中的对象
                        Object listObj = getM.invoke(field.get(obj), i);
                        //测试是否可以获取到list中对象的属性的值
                        Field[] fieldList = listObj.getClass().getDeclaredFields();
                        for (Field field1 : fieldList) {
                            if (field1 == null || field1.getType()==null) {
                                continue;
                            }
                            field1.setAccessible(true);

                            if(field1.get(listObj) == null){
                                continue;
                            }
                            if (field1.isAnnotationPresent(EncryptionSM4.class)) {
                                field1.set(listObj, DataSecurityUtil.encryption((String) field1.get(listObj),config.getRegistrationCheck().getEncryptionKey()));
                                break;
                            }
                        }
                    }
                }
                //判断根据自己的业务逻辑,有效修改
            }else if (!field.getType().equals(String.class) && !field.getType().equals(BigDecimal.class) && null != field.getType().getDeclaredFields() && field.getType().getDeclaredFields().length > 0) {
                encrypt(field.get(obj));
            }
        }
    }

因为我的加密字段都在list集合中,如果有的在普通对象中,可以在加个判断。

   // 若属性有该注解,且属性为字符串类型,则根据对应的加密方式进行加密
  if (field.isAnnotationPresent(Security.class) && field.getType().equals(String.class)) {
       // 获取加密方式
       String type = field.getAnnotation(Security.class).type();
       switch (type) {
           case "SM4":
               // 可自定义加密
               field.set(obj, "ttt" + field.get(obj));
               break;
           default:
               break;
       }

注:根据自己的业务需求进行更改,本文知识提供一些思路

上一篇:解决Aireplay-ng信道问题


下一篇:Angular