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;
}
注:根据自己的业务需求进行更改,本文知识提供一些思路