问题分析
数据脱敏,即对前端展示的部分数据做模糊处理(用*号代替一部分数据)
如脱敏前:
脱敏后:
当然,可以自己决定对数据的哪一部分进行脱敏,或者整个数据脱敏。
现要求针对不同的数据展示页面,需要对指定的字段(上述例子中除序号外的四个字段)进行脱敏。
自定义注解@Desensitize
考虑到需要脱敏查询的接口,返回类型统一为VO,故使用一个自定义注解,在VO中对需要脱敏的字段进行标识,即可在数据返回前,对特定的字段进行脱敏处理
创建注解@Desensize
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Desensitize {
}
VO类:
@Data
@ApiModel
public class ProjectVO {
@ApiModelProperty(notes = "主键")
private String id;
@ApiModelProperty(notes = "项目编码")
private String pmCode;
@Desensitize
@ApiModelProperty(notes = "项目名称")
private String pmName;
@ApiModelProperty(notes = "创建时间")
private Date createTime;
@ApiModelProperty(notes = "更新时间")
private Date updateTime;
}
如上,项目编码、项目名称被@Densitize注解标识,代码数据返回前需要脱敏处理
获取脱敏字段并进行脱敏处理
List<ProjectVO> list = service.list(); // 获取原始数据
desensitizeObject(list, desensitization); // 数据脱敏,desensitization为是否需要脱敏
private <T> void desensitizeObject(List<T> list, Integer desensitization) {
// 如果desensitization不为1,则不需要脱敏
if (desensitization != null && desensitization == 1) {
for (T bean : list) {
desensitizeObject(bean); // 对list中每一个元素进行脱敏
}
}
}
// 脱敏方法
private void desensitizeObject(Object obj) {
Class<?> clazz = obj.getClass(); // 获取类
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Desensitize.class)) { // 遍历每一个字段,并判断是否被@Desensitize注解标识
try {
field.setAccessible(true); // 使VO中private字段能够被外部访问
Object value = field.get(obj);
if (value != null) {
field.set(obj, CommonUtil.desensitization(value.toString())); // 数据脱敏,脱敏方法根据业务要求编写
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to desensitize field", e);
}
}
}
}
针对不同的页面,只需要使用@Desensitize注解对VO类中需要脱敏的字段进行标识,即可实现脱敏功能。灵活性、可扩展性得到提高。