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、 编写方法,解析注解
/**
* 加密
*
* @param obj
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private void encrypt(Object obj) throws Exception {
if (null == obj) {
return;
}
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
Class<?> fieldType = field.getType();
// 字符串
if (fieldType == String.class) {
if (field.isAnnotationPresent(EncryptionSM4.class)) {
field.setAccessible(Boolean.TRUE);
handleField(obj, field, config.getRegistrationCheck().getEncryptionKey());
field.setAccessible(Boolean.FALSE);
}
} else if (List.class.isAssignableFrom(fieldType)) {
// 判断是否为list
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
Class genericClazz = (Class) pt.getActualTypeArguments()[0];
// list<String>
if (genericClazz == String.class) {
if (field.isAnnotationPresent(EncryptionSM4.class)) {
field.setAccessible(Boolean.TRUE);
List list = (List) field.get(obj);
if (list != null && !list.isEmpty()) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) != null) {
list.set(i, DataSecurityUtil.encryption((String) list.get(i),
config.getRegistrationCheck().getEncryptionKey()));
}
}
}
field.setAccessible(Boolean.FALSE);
}
} else {
field.setAccessible(Boolean.TRUE);
List list = (List) field.get(obj);
if (list != null && !list.isEmpty()) {
for (Object subObj : list) {
encrypt(subObj);
}
}
field.setAccessible(Boolean.FALSE);
}
}
} else if (fieldType.getName().startsWith("com.sleb.transit.cbittransit.model")) {
// 判断属于自定义的model
field.setAccessible(Boolean.TRUE);
encrypt(field.get(obj));
field.setAccessible(Boolean.FALSE);
} else if (fieldType == Object.class) {
field.setAccessible(Boolean.TRUE);
encrypt(field.get(obj));
field.setAccessible(Boolean.FALSE);
}
}
}
private static void handleField(Object obj, Field field, String secretKey) throws Exception {
if (null == obj) {
return;
}
// 说明:sm4依赖包传入null会出现空指针异常
Object item = field.get(obj);
if (null != item) {
field.set(obj, DataSecurityUtil.encryption((String) field.get(obj), secretKey));
}
}
因为我的加密字段都在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;
}
注:根据自己的业务需求进行更改,本文知识提供一些思路