Hutool:一行代码搞定数据脱敏
来源 | OSCHINA 社区
作者 | 京东云开发者-京东科技 孙扬威
原文链接:https://my.oschina.net/u/4090830/blog/10094536
1. 什么是数据脱敏
1.1 数据脱敏的定义
1.2 常用脱敏规则
2. Hutool 工具介绍
2.1 引入 Maven 配置
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
2.2 Hutool 包含的组件
模块 | 介绍 |
---|---|
hutool-aop | JDK 动态代理封装,提供非 IOC 下的切面支持 |
hutool-bloomFilter | 布隆过滤,提供一些 Hash 算法的布隆过滤 |
hutool-cache | 简单缓存实现 |
hutool-core | 核心,包括 Bean 操作、日期、各种 Util 等 |
hutool-cron | 定时任务模块,提供类 Crontab 表达式的定时任务 |
hutool-crypto | 加密解密模块,提供对称、非对称和摘要算法封装 |
hutool-db | JDBC 封装后的数据操作,基于 ActiveRecord 思想 |
hutool-dfa | 基于 DFA 模型的多关键字查找 |
hutool-extra | 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等) |
hutool-http | 基于 HttpUrlConnection 的 Http 客户端封装 |
hutool-log | 自动识别日志实现的日志门面 |
hutool-script | 脚本执行封装,例如 Javascript |
hutool-setting | 功能更强大的 Setting 配置文件和 Properties 封装 |
hutool-system | 系统参数调用封装(JVM 信息等) |
hutool-json | JSON 实现 |
hutool-captcha | 图片验证码实现 |
hutool-poi | 针对 POI 中 Excel 和 Word 的封装 |
hutool-socket | 基于 Java 的 NIO 和 AIO 的 Socket 封装 |
hutool-jwt | JSON Web Token (JWT) 封装实现 |
hutool-all
方式引入所有模块,本文所使用的数据脱敏工具就是在 hutool.core 模块。2.3 Hutool 支持的脱敏数据类型
3. Hutool 数据脱敏实操
3.1 使用 Hutool 工具类一行代码实现脱敏
importcn.hutool.core.util.DesensitizedUtil;
importorg.junit.Test;
importorg.springframework.boot.test.context.SpringBootTest;
/**
*
* @description: Hutool实现数据脱敏
*/
@SpringBootTest
publicclassHuToolDesensitizationTest{
@Test
publicvoidtestPhoneDesensitization(){
String phone="13723231234";
System.out.println(DesensitizedUtil.mobilePhone(phone));//输出:137****1234
}
@Test
publicvoidtestBankCardDesensitization(){
String bankCard="6217000130008255666";
System.out.println(DesensitizedUtil.bankCard(bankCard));//输出:6217 **** **** *** 5666
}
@Test
publicvoidtestIdCardNumDesensitization(){
String idCardNum="411021199901102321";
//只显示前4位和后2位
System.out.println(DesensitizedUtil.idCardNum(idCardNum,4,2));//输出:4110************21
}
@Test
publicvoidtestPasswordDesensitization(){
String password="www.jd.com_35711";
System.out.println(DesensitizedUtil.password(password));//输出:****************
}
}
3.2 配合 JackSon 通过注解方式实现脱敏
/**
* @author
* @description:脱敏策略枚举
*/
publicenumDesensitizationTypeEnum{
//自定义
MY_RULE,
//用户id
USER_ID,
//中文名
CHINESE_NAME,
//身份证号
ID_CARD,
//座机号
FIXED_PHONE,
//手机号
MOBILE_PHONE,
//地址
ADDRESS,
//电子邮件
EMAIL,
//密码
PASSWORD,
//中国大陆车牌,包含普通车辆、新能源车辆
CAR_LICENSE,
//银行卡
BANK_CARD
}
@Retention (RetentionPolicy.RUNTIME):运行时生效。
@Target (ElementType.FIELD):可用在字段上。
@JacksonAnnotationsInside:此注解可以点进去看一下是一个元注解,主要是用户打包其他注解一起使用。
@JsonSerialize:上面说到过,该注解的作用就是可自定义序列化,可以用在注解上,方法上,字段上,类上,运行时生效等等,根据提供的序列化类里面的重写方法实现自定义序列化。
/**
* @author
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using =DesensitizationSerialize.class)
public@interface Desensitization{
/**
* 脱敏数据类型,在MY_RULE的时候,startInclude和endExclude生效
*/
DesensitizationTypeEnumtype()defaultDesensitizationTypeEnum.MY_RULE;
/**
* 脱敏开始位置(包含)
*/
intstartInclude()default0;
/**
* 脱敏结束位置(不包含)
*/
intendExclude()default0;
}
/**
* @author
* @description: 自定义序列化类
*/
@AllArgsConstructor
@NoArgsConstructor
publicclassDesensitizationSerializeextendsJsonSerializer<String> implementsContextualSerializer{
privateDesensitizationTypeEnum type;
privateInteger startInclude;
privateInteger endExclude;
@Override
publicvoidserialize(String str,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throwsIOException{
switch(type){
// 自定义类型脱敏
case MY_RULE:
jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude));
break;
// userId脱敏
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),1,2));
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
publicJsonSerializer<?> createContextual(SerializerProvider serializerProvider,BeanProperty beanProperty)throwsJsonMappingException{
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,开始位置,结束位置。
returnnewDesensitizationSerialize(desensitization.type(), desensitization.startInclude(),
desensitization.endExclude());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}
/**
*
* @description:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
publicclassTestPojo{
privateString userName;
@Desensitization(type =DesensitizationTypeEnum.MOBILE_PHONE)
privateString phone;
@Desensitization(type =DesensitizationTypeEnum.PASSWORD)
privateString password;
@Desensitization(type =DesensitizationTypeEnum.MY_RULE, startInclude =0, endExclude =2)
privateString address;
}
接下来写一个测试的 controller
@RestController
publicclassTestController{
@RequestMapping("/test")
publicTestPojotestDesensitization(){
TestPojo testPojo =newTestPojo();
testPojo.setUserName("我是用户名");
testPojo.setAddress("地球中国-北京市通州区京东总部2号楼");
testPojo.setPhone("13782946666");
testPojo.setPassword("sunyangwei123123123.");
System.out.println(testPojo);
return testPojo;
}
}
4. 其他常见的数据脱敏工具推荐
4.1 Apache ShardingSphere
4.2 FastJSON
基于注解 @JSONField 实现:需要自定义一个用于脱敏的序列化的类,然后在需要脱敏的字段上通过 @JSONField 中的 serializeUsing 指定为我们自定义的序列化类型即可。
基于序列化过滤器:需要实现 ValueFilter 接口,重写 process 方法完成自定义脱敏,然后在 JSON 转换时使用自定义的转换策略。具体实现可参考这篇文章: https://juejin.cn/post/7067916686141161479
4.3 Mybatis-mate
# Mybatis Mate 配置
mybatis-mate:
cert:
grant: jxftsdfggggx
license: GKXP9r4MCJhGID/DTGigcBcLmZjb1YZGjE4GXaAoxbtGsPC20sxpEtiUr2F7Nb1ANTUekvF6Syo6DzraA4M4oacwoLVTglzfvaEfadfsd232485eLJK1QsskrSJmreMnEaNh9lsV7Lpbxy9JeGCeM0HPEbRvq8Y+8dUt5bQYLklsa3ZIBexir+4XykZY15uqn1pYIp4pEK0+aINTa57xjJNoWuBIqm7BdFIb4l1TAcPYMTsMXhF5hfMmKD2h391HxWTshJ6jbt4YqdKD167AgeoM+B+DE1jxlLjcpskY+kFs9piOS7RCcmKBBUOgX2BD/JxhR2gQ==
5. 总结
6. 参考内容
往期推荐
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦
微信扫码关注该文公众号作者
戳这里提交新闻线索和高质量文章给我们。
来源: qq
点击查看作者最近其他文章