@TOC**
一、实现步骤概述
1、先定义一个自定义注解来标记需要做数据脱敏的方法
2、使用spring boot 自带的@ControllerAdvice去对有这个注解标记的方法进行处理。注:使用@ControllerAdvice注解需要新建一个类去实现ResponseBodyAdvice这个接口
下面展示一些 ,实现这个接口的类,可以修改返回值直接作为 ResponseBody类型处理器的返回值。在beforeBodyWrite这个方法中进行接口返回前的处理
@ControllerAdvice
public class DataMaskingAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return null != returnType.getMethodAnnotation(DataMasking.class);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
String string = JSON.toJSONString(body, new DataMaskingValueFilter(), SerializerFeature.WriteDateUseDateFormat);
return JSON.parseObject(string, Object.class);
}
}
二、详细说明
1、什么是自定义注解
(1) 自定义注解与类和接口的定义类似
(2) 关键字为:@interface 但该自定义注解上方需要加上一些注解去说明该注解的使用范围与使用时间点,如下@Target注解表示该注解应该在方法上进行使用,@Retention注解表示该注解的作用时间在运行和编译时都起作用
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataMasking {
}
2、敏感词过滤器类的创建
public class DataMaskingValueFilter implements ValueFilter {
@Override
public Object process(Object object, String name, Object value) {
if ((object instanceof ApiResult || object instanceof com.che300.common.pojo.ApiResult) && "data".equals(name)){
Object result = null;
if (object instanceof ApiResult){
result = ((ApiResult) object).getData();
}
if (object instanceof com.che300.common.pojo.ApiResult){
result = ((com.che300.common.pojo.ApiResult) object).getData();
}
if (result instanceof Date) {
return DateUtil.formatDateTime((Date) value);
}
Field field;
if (result instanceof String) {
try {
field = object.getClass().getDeclaredField(name);
ParamMasking annotation = field.getAnnotation(ParamMasking.class);
if (null != annotation) {
return ((String) value).replaceAll(annotation.value().getPattern(), annotation.value().getTargetChar());
}
} catch (NoSuchFieldException e) {
}
}
//针对列表数据进行脱敏
if (result instanceof PageInfo || result instanceof Page){
List<?> list = null;
if (result instanceof PageInfo){
list = (List<?>)((PageInfo) result).getList();
}
if (result instanceof Page){
list = (List<?>)((Page) result).getList();
}
if (list != null && list.size() > 0){
for (Object o : list) {
Field[] fields = o.getClass().getDeclaredFields();
for (Field field1 : fields) {
ParamMasking annotation = field1.getAnnotation(ParamMasking.class);
if (null != annotation) {
Object value1 = ReflectUtil.getFieldValue(o, field1.getName());
if ( value1 != null){
value1 = ((String) value1).replaceAll(annotation.value().getPattern(), annotation.value().getTargetChar());
ReflectUtil.setFieldValue(o, field1.getName(), value1.toString());
}
}
}
}
}
}
}
return value;
}
}
3、在指定列表中取使用该注解达到数据脱敏的效果
如在getOrderList这个方法上加@DataMasking注解
@RequestMapping("/getOrderList")
@DataMasking
public ApiResult getOrderList(GpsDto gpsDto) {
ApiResult result;
try {
DataAuthority dataAuthority = new DataAuthority(getCurrentUser());
Page<GpsOrder> page = gpsInstallService.getGpsOrderList(gpsDto,dataAuthority);
return ApiResult.success(page);
} catch (MyException e) {
logger.error("gps安装页面获取订单列表失败", e);
result = ApiResult.failure(ResultCode.SYSTEM_EXCEPTION);
}
return result;
}