SpringBoot 实现数据脱敏
- 前言
- Hutool 实现数据脱敏
- 引入依赖
- 脱敏工具类
- 代码实现
- 使用注解的方式
- 定义枚举
- 自定义序列化类
- 定义注解
- 测试
前言
数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。
数据脱敏常用规则有替换、重排、加密、截断、掩码
- 替换:用其他字符或者符号替换原始数据中的字符或者符号,例如将手机号码中间四位替换为星号。
- 重排:将原始数据中的字符或者符号重新排列,例如将身份证号码中的数字重新排列。
- 加密:使用加密算法对原始数据进行加密,例如使用AES算法对银行卡号进行加密。
- 截断:将原始数据中的一部分截取掉,例如只保留姓名的首字母。
- 掩码:使用特定符号或者字符掩盖原始数据中的一部分,例如使用星号掩盖信用卡号码中的一部分数字。
Hutool 实现数据脱敏
hutool ——一个 Java 基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种 Util 工具类
官方文档:简介 | Hutool
引入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
脱敏工具类
hutool 使用信息脱敏工具——DesensitizedUtil 实现脱敏操作
现阶段支持的脱敏数据类型包括:
- 用户id
- 中文姓名
- 身份证号
- 座机号
- 手机号
- 地址
- 电子邮件
- 密码
- 中国大陆车牌,包含普通车辆、新能源车辆
- 银行卡
自定义隐藏可以使用StrUtil.hide
方法完成
代码实现
public class HutoolDesensitized {
public static void main(String[] args) {
String phone = "15888888888";
System.out.println(DesensitizedUtil.mobilePhone(phone)); // 158****8888
String idCard = "490508200001010001";
System.out.println(DesensitizedUtil.idCardNum(idCard,4,4)); // 4905**********0001
String password = "dddd3343ssxx";
System.out.println(DesensitizedUtil.password(password)); // ************ 对于密码则只保留位数
String bankCard = "8845600134008139446";
System.out.println(DesensitizedUtil.bankCard(bankCard)); // 8845 **** **** *** 9446
}
}
使用注解的方式
使用 SpringBoot 自带的 jackson 自定义序列化实现,在 json 进行序列化返回时,实现脱敏
定义枚举
public enum DesensitizationTypeEnum {
// 自定义
CUSTOM_RULE,
// 用户id
USER_ID,
// 中文名
CHINESE_NAME,
// 身份证号
ID_CARD,
// 座机号
FIXED_PHONE,
// 手机号
MOBILE_PHONE,
// 地址
ADDRESS,
// 电子邮件
EMAIL,
// 密码
PASSWORD,
// 车牌
CAR_LICENSE,
//银行卡
BANK_CARD
}
自定义序列化类
继承JsonSerializer,实现 ContextualSerializer 接口
@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {
private DesensitizationTypeEnum type;
private Integer startInclude;
private Integer endExclude;
@Override
public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
switch (type) {
// 自定义类型脱敏
case CUSTOM_RULE:
jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude));
break;
// 用户名脱敏
case USER_ID:
jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
break;
// 中文姓名脱敏
case CHINESE_NAME:
jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));
break;
// 身份证脱敏
case ID_CARD:
jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 4, 4));
break;
// 固定电话脱敏
case FIXED_PHONE:
jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
break;
// 手机号脱敏
case MOBILE_PHONE:
jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));
break;
// 地址脱敏
case ADDRESS:
jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));
break;
// 邮箱脱敏
case EMAIL:
jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));
break;
// 密码脱敏
case PASSWORD:
jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));
break;
// 中国车牌脱敏
case CAR_LICENSE:
jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));
break;
// 银行卡脱敏
case BANK_CARD:
jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));
break;
default:
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
// 判断数据类型是否为String类型
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
// 获取定义的注解
Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
// 为null
if (desensitization == null) {
desensitization = beanProperty.getContextAnnotation(Desensitization.class);
}
// 不为null
if (desensitization != null) {
// 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。
return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),
desensitization.endExclude());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}
定义注解
@JsonSerialize
定义 json 序列化器
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {
/**
* 脱敏数据类型,在 CUSTOM_RULE 的时候,startInclude 和 endExclude 生效
*/
DesensitizationTypeEnum type() default DesensitizationTypeEnum.CUSTOM_RULE;
/**
* 脱敏开始位置(包含)
*/
int startInclude() default 0;
/**
* 脱敏结束位置(不包含)
*/
int endExclude() default 0;
}
测试
定义一个测试类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestUser {
@Desensitization(type = DesensitizationTypeEnum.MOBILE_PHONE)
private String phone;
@Desensitization(type = DesensitizationTypeEnum.EMAIL)
private String email;
@Desensitization(type = DesensitizationTypeEnum.CUSTOM_RULE,startInclude = 3, endExclude = 9)
private String customEntity;
}
测试接口
@RestController
@RequestMapping
public class TestController {
@GetMapping("/test")
public TestUser testDesensitization() {
TestUser testUser = new TestUser();
testUser.setPhone("15888888888");
testUser.setEmail("dadfd_333@163.com");
testUser.setCustomEntity("dfkdjf3434__495kdjf@@");
return testUser;
}
}
返回数据