需求为:
为指定列表查询接口(分页),添加指定字段的脱敏信息,脱敏规则自定义.

定义表明方法返回值需要脱敏的注解

此注解用于controller的方法上

1
2
3
4
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DesensitizationData {
}

定义脱敏规则注解

此注解用于实体类字段上

1
2
3
4
5
6
7
8
9
10
11

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DesensitizationFormat {
/**
* 替换指定字符串的指定区间内字符为"*" int数组必须是两位,小于两位使用默认值
* [startInclude,endInclude)]
*/
int[] interval() default {0,99};
}

定义脱敏切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

@Aspect
@Component
@Slf4j
@Order(2) //自定义顺序
public class DesensitizationAspect {
/**
* 处理敏感数据
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("@annotation(org.jeecg.common.aspect.annotation.DesensitizationData)")
public Object handleSensitiveData(ProceedingJoinPoint joinPoint) throws Throwable {
log.debug("开始数据脱敏处理");
Object returnVal = joinPoint.proceed();

if (returnVal instanceof Result<?>) {
Result<?> resultWrapper = (Result<?>) returnVal;
Object result = resultWrapper.getResult();
if (result instanceof IPage<?>) {
IPage<?> page = (IPage<?>) result;
for (Object record : page.getRecords()) {
if (record != null) {
DesensitizationUtil.desensitizeData(record);
}
}
}
}
log.debug("数据脱敏处理完成!");
return returnVal;
}

}

定义脱敏工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Slf4j
public class DesensitizationUtil {
public static void desensitizeData(Object data) {
for (Field field : oConvertUtils.getAllFields(data)) {
DesensitizationFormat annotation = field.getAnnotation(DesensitizationFormat.class);
if (annotation != null) {
try {
field.setAccessible(true);
Object value = field.get(data);
if (value != null) {
field.set(data, desensitize(value.toString(), annotation));
}
} catch (IllegalAccessException e) {
log.error("Failed to access field", e);
}
}
}
}

public static String desensitize(String rowData, DesensitizationFormat type) {
int[] interval = type.interval();
if (interval.length < 2) {
log.warn("DesensitizationFormat interval length less than 2, use default interval [0,99]");
interval = new int[]{0, 99};
}
// 此处使用hutool工具类,不想使用可自行实现将字符串指定区间的字符替换为*
return StrUtil.hide(rowData, interval[0], rowData.length() - interval[1]);
}
}

使用方法

1.将@DesensitizationData注解写在需要脱敏的列表接口上
2.将上面结果返回实体类中需要脱敏的字段上添加@DesensitizationFormat注解,并定义脱敏规则.如手机号一般是保留前三位和后四位@DesensitizationFormat(interval = {3,4})

启动服务调用接口测试即可