脱敏与加解密_自定义注解实现加解密及脱敏

title: ep_自定义注解实现加解密及脱敏

date: 2020-04-28 09:44

定义自定义注解

@Documented

@Target({ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

@Order(Ordered.HIGHEST_PRECEDENCE)

public @interface PrivateData {

}

@Documented

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Order(Ordered.HIGHEST_PRECEDENCE)

public @interface PrivateDataMethod {

}

首先定义两个自定义注解,privateData和privateDataMethod,分别将@Target属性定义为FIELD和METHOD。

构造AOP逻辑

申明一个切入点

@Pointcut("@annotation(com.max.base.services.annotation.PrivateDataMethod)")

public void annotationPointCut() {

}

对所有添加@privateDataMethod注解的方法进行切入。

申明通知

@Around("annotationPointCut()")

public Object around(ProceedingJoinPoint joinPoint) {

Object responseObj = null;

try {

Object[] request = joinPoint.getArgs();

for (Object object : request) {

if (object instanceof Collection) {

Collection collection = (Collection) object;

collection.forEach(var -> {

try {

handleEncrypt(var);

} catch (IllegalAccessException e) {

e.printStackTrace();

}

});

} else {

handleEncrypt(object);

}

}

responseObj = joinPoint.proceed();

if (responseObj instanceof Collection) {

Collection collection = (Collection) responseObj;

collection.forEach(var -> {

try {

handleDecrypt(var);

} catch (IllegalAccessException e) {

e.printStackTrace();

}

});

} else {

handleDecrypt(responseObj);

}

} catch (Throwable throwable) {

throwable.printStackTrace();

log.error("SecureFieldAop 异常{}", throwable);

}

return responseObj;

}

申明Aroud通知,对于方法输入输出的对象进行判断,如果是非集合对象则直接进行加解密操作,否则则拆分集合,逐一操作

处理加解密

/**

* 处理加密

* @param requestObj

*/

private void handleEncrypt(Object requestObj) throws IllegalAccessException {

if (Objects.isNull(requestObj)) {

return;

}

Field[] fields = requestObj.getClass().getDeclaredFields();

for (Field field : fields) {

boolean hasSecureField = field.isAnnotationPresent(PrivateData.class);

if (hasSecureField) {

Boolean accessible = field.isAccessible();

if (!accessible) {

field.setAccessible(true);

}

String plaintextValue = (String) field.get(requestObj);

String encryptValue = AseUtil.encrypt(plaintextValue, secretKey);

field.set(requestObj, encryptValue);

if (!accessible) {

field.setAccessible(false);

}

}

}

}

通过反射获取对象的Field列表,对于拥有@PrivateData注解的字段执行encryptValue()方法并用加密后的字符串覆盖原字段。

解密逻辑与加密类似,不做赘述。

测试

标识insert()方法为需要加密的方法

public interface CmTenantMapper {

int deleteByPrimaryKey(Long id);

@PrivateDataMethod

int insert(CmTenant record);

int insertSelective(CmTenant record);

CmTenant selectByPrimaryKey(Long id);

int updateByPrimaryKeySelective(CmTenant record);

int updateByPrimaryKey(CmTenant record);

}

对传入对象中需要加密的字段添加注解

public class CmTenant {

private Long id;

private String tenantId;

@PrivateData

private String tenantName;

private String createBy;

private Date createDate;

private String updateBy;

private Date updateDate;

private String remarks;

private Byte delFlag;

//set get...

调用insert方法查看数据保存结果

传入对象

{

"createBy": "可乐可不乐",

"delFlag": "NOTDELETE",

"remarks": "测试加密",

"tenantId": "996",

"tenantName": "椅子团队出品",

"updateBy": "可乐可不乐"

}

数据库保存对象

解密测试不做注释,大家自行尝试

脱敏逻辑

脱敏逻辑与加解密基本一致,需要注意的一点是脱敏的注解需要添加type类型

@Documented

@Target({ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

@Order(Ordered.HIGHEST_PRECEDENCE)

public @interface MaskingField {

MaskingTypeEnum type();

}

在MaskingTypeEnum中定义脱敏的分类

public enum MaskingTypeEnum {

/*身份证号码*/

ID_CARD,

/*手机号码*/

PHONE,

/*地址*/

ADDRESS,

/*姓名*/

NAME

}

在使用是MaskingTypeEnum时标识字段的类型

@MaskingField(type = MaskingTypeEnum.NAME)

private String cpName;

后续~~bug~~功能大家自行研究, peace~

本文由博客一文多发平台 OpenWrite 发布!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值