# sensitive-plus
**Repository Path**: touchren/sensitive-plus
## Basic Information
- **Project Name**: sensitive-plus
- **Description**: 数据脱敏插件,目前支持地址脱敏、银行卡号脱敏、中文姓名脱敏、固话脱敏、身份证号脱敏、手机号脱敏、密码脱敏
一个是正则脱敏、另外一个根据显示长度脱敏,默认是正则脱敏,可以根据自己的需要配置自己的规则
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 134
- **Created**: 2024-07-29
- **Last Updated**: 2024-07-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# README
## 1、说明
数据脱敏插件,目前支持地址脱敏、银行卡号脱敏、中文姓名脱敏、固话脱敏、身份证号脱敏、手机号脱敏、密码脱敏。
一个是正则脱敏、另外一个根据显示长度脱敏,默认是正则脱敏,可以根据自己的需要配置自己的规则。
具体使用请参考单元测试下的
```
com.yhq.sensitive.UserEntity
com.yhq.sensitive.SimpleEntity
com.yhq.sensitive.SensitiveTests
com.yhq.sensitive.SensitiveLogTests
com.yhq.sensitive.converter.SensitiveLogbackMessageConverterTest
```
## 2、注解说明
| 注解名称 | 作用描述 |
|------------------------------|:---------------:|
| @SensitiveLengthAddress | 使用显示长度规则对地址脱敏 |
| @SensitiveLengthBankCard | 使用显示长度规则对银行卡脱敏 |
| @SensitiveLengthChineseName | 使用显示长度规则对中文姓名脱敏 |
| @SensitiveLengthEmail | 使用显示长度规则对邮箱脱敏 |
| @SensitiveLengthFixedPhone | 使用显示长度规则对固定号码脱敏 |
| @SensitiveLengthIdCard | 使用显示长度规则对身份证号脱敏 |
| @SensitiveLengthMobile | 使用显示长度规则对手机号码脱敏 |
| @SensitiveLengthPassword | 使用显示长度规则对密码脱敏 |
| @SensitivePatternAddress | 使用正则规则对地址脱敏 |
| @SensitivePatternBankCard | 使用正则规则对银行卡脱敏 |
| @SensitivePatternChineseName | 使用正则规则对中文姓名脱敏 |
| @SensitivePatternEmail | 使用正则规则对邮箱脱敏 |
| @SensitivePatternFixedPhone | 使用正则规则对固定号码脱敏 |
| @SensitivePatternIdCard | 使用正则规则对身份证号脱敏 |
| @SensitivePatternMobile | 使用正则规则对手机号码脱敏 |
| @SensitivePatternPassword | 使用正则规对密码脱敏 |
## 3、重写脱敏展示的内容
| 注解名称 | 作用描述 |
|-------------------------------------------------------|:------:|
| @SensitiveInfo(strategy = SensitiveAddress.class) | 地址脱敏 |
| @SensitiveInfo(strategy = SensitiveBankCard.class) | 银行卡脱敏 |
| @SensitiveInfo(strategy = SensitiveChineseName.class) | 中文姓名脱敏 |
| @SensitiveInfo(strategy = SensitiveEmail.class) | 邮箱脱敏 |
| @SensitiveInfo(strategy = SensitiveFixedPhone.class) | 固话脱敏 |
| @SensitiveInfo(strategy = SensitiveIdCard.class) | 身份证脱敏 |
| @SensitiveInfo(strategy = SensitiveMobile.class) | 手机号码脱敏 |
| @SensitiveInfo(strategy = SensitivePassword.class) | 密码脱敏 |
如11位的手机号,默认脱敏策略是显示前三后四,如 `183****1309`,自定义策略后
```
@SensitiveInfo(strategy = SensitiveMobile.class,begin = 4,end = 3)
```
显示结果为`1837****309`
银行卡号自定义脱敏,例如
```
@SensitiveInfo(pattern = "(?<=\\w{6})\\w(?=\\w{4})",replaceChar = "*")
```
## 4、日志脱敏
日志脱敏有2种实现办法:
其一,基于Logback实现自定义`ch.qos.logback.classic.pattern.MessageConverter`,重写`convert()`方法。
其二,打印日志之前先对消息内容进行脱敏。
### 基于MessageConverter
需要在`logback.xml`中明确指定自定义MessageConverter,示例:
```xml
```
这种方式实现的日志脱敏需要在打印日志时使用特定的格式,主要依赖正则表达式规则,如:
```
// 对手机号进行脱敏
// 处理正则:(mobile|telephone)([:|=|,| ]+)(\w{3})(\w{4})(\w{4})
log.info("mobile:{}", mobile);
```
另外,该方式实现的日志脱敏存在性能瓶颈,因为在`convert()`方法中需要对每条日志消息应用所有的脱敏规则。
### 先脱敏再打印
日志脱敏先在应用层先对日志内容脱敏再打印,分为两种情况处理。
#### 字符串
对于输出到日志中的内容是单纯的字符串这种情况,直接调用工具方法先脱敏后再打印到日志。
```
String chineseName = "赵子龙";
String mobile = "13242429876";
String fixPhone = "010-32342214";
String address = "西川成都蜀国大将军府";
String idCard = "123456789012345678";
String bankCard = "6666666666666666666";
String email = "zhaozilong@chengdu.com";
String password = "1234567890";
// 中文名
LOGGER.info("chineseName: {}", SensitiveInfoUtils.chineseName(chineseName));
// 手机号
LOGGER.info("mobile: {}", SensitiveInfoUtils.mobilePhone(mobile));
// 固定电话
LOGGER.info("fixPhone: {}", SensitiveInfoUtils.fixedPhone(fixPhone));
// 地址
LOGGER.info("address: {}", SensitiveInfoUtils.address(address));
// 身份证号
LOGGER.info("idCard: {}", SensitiveInfoUtils.idCard(idCard));
// 银行卡号
LOGGER.info("bankCard: {}", SensitiveInfoUtils.bankCard(bankCard));
// 邮箱
LOGGER.info("email: {}", SensitiveInfoUtils.email(email));
// 密码
LOGGER.info("password: {}", SensitiveInfoUtils.password(password));
```
在日志中打印脱敏后的内容:
```
14:24:54.195 [main] INFO com.yhq.sensitive.SensitiveLogTests - chineseName: 赵**
14:24:54.197 [main] INFO com.yhq.sensitive.SensitiveLogTests - mobile: 132****9876
14:24:54.198 [main] INFO com.yhq.sensitive.SensitiveLogTests - fixPhone: ********2214
14:24:54.198 [main] INFO com.yhq.sensitive.SensitiveLogTests - address: 西川成都******
14:24:54.198 [main] INFO com.yhq.sensitive.SensitiveLogTests - idCard: **************5678
14:24:54.198 [main] INFO com.yhq.sensitive.SensitiveLogTests - bankCard: 666666*********6666
14:24:54.198 [main] INFO com.yhq.sensitive.SensitiveLogTests - email: z*********@chengdu.com
14:24:54.198 [main] INFO com.yhq.sensitive.SensitiveLogTests - password: ******
```
#### 实体对象
如果打印到日志中的内容为实体对象,在打印日志之前将对象序列化为JSON字符串。
user为实体对象
```
log.info(SensitiveJsonUtils.toJson(user));
```
整体测试结果如下
```
{
"userNamePattern": "张**",
"userNameLength": "张**",
"passwordPattern": "************",
"passwordLength": "******",
"idCardPattern": "**************6789",
"idCardLength": "**************6789",
"fixedPhonePattern": "********4321",
"fixedPhoneLength": "********4321",
"mobilePattern": "156****0987",
"mobileLength": "156****0987",
"addressPattern": "北京市朝阳*****128号",
"addressLength": "北京市朝阳区望京路王家村张******",
"emailPattern": "23345acv***@qq.com",
"emailLength": "2**********@qq.com",
"bankCardPattern": "621226*********2455",
"bankCardCustomizePattern": "621226*********2455",
"bankCardLength": "621226*********2455"
}
```
目前支持3种JSON序列化组件:
[Jackson](https://github.com/FasterXML/jackson-databind)
[Fastjson](https://github.com/alibaba/fastjson)
[Gson](https://github.com/google/gson)
## 5、接口数据脱敏
目前支持基于Spring MVC框架的JSON响应数据脱敏处理。
具体实现是在需要脱敏的实体属性上使用脱敏注解进行标注,并应用自定义`HttpMessageConverter`。
```java
public class Account {
private Long id = 0L;
@SensitiveLengthChineseName
private String username = "";
@SensitiveLengthPassword
private String password = "";
private Integer age = 0;
private Short sex = 0;
private Date createTime = null;
private Date updateTime = null;
}
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void extendMessageConverters(List> converters) {
super.extendMessageConverters(converters);
// 将自定义HttpMessageConverter放在第一个,确保生效
converters.add(0, new SensitiveFastJsonMessageConverter());
}
}
```
这样,在接口返回JSON数据时会自动对使用了脱敏注解的属性进行处理,响应数据示例:
```json
{
"id": 1,
"username": "张**",
"password": "******",
"age": 23,
"sex": 1,
"createTime": null,
"updateTime": null
}
```
参考[SpringBoot中自定义HttpMessageConverter](https://juejin.cn/post/7007715644774825992)
## 6、DFA算法 敏感词库脱敏
读取敏感词库 com.yhq.sensitive.util.SensitiveWordInit
敏感词工具类 com.yhq.sensitive.util.SensitiveWordFilter
由于一些词汇违规,所以以拼音代替,请自行脑补
| 方法 | 作用描述 |
|-------------------------------------------------------------------|:---------:|
| boolean isContainSensitiveWord(String txt,int matchType) | 判断是否存在敏感词 |
| Set getSensitiveWord(String txt , int matchType) | 获取敏感词 |
| replaceSensitiveWord(String txt,int matchType,String replaceChar) | 敏感词替代 |
单元测试类
```
com.yhq.sensitive.SensitiveWordFilterTest.test
测试结果如下:
17:02:43.507 [main] INFO com.yhq.sensitive.SensitiveWordFilterTest - 敏感词的数量:893
17:02:43.511 [main] INFO com.yhq.sensitive.SensitiveWordFilterTest - 待检测语句字数:184
17:02:43.511 [main] INFO com.yhq.sensitive.SensitiveWordFilterTest - 语句中包含敏感词的个数为:3个
17:02:43.511 [main] INFO com.yhq.sensitive.SensitiveWordFilterTest - 总共消耗时间为:18
```
## 7、其他
该脱敏组件的基础实现基于开源项目:[sensitive-plus](https://gitee.com/strong_sea/sensitive-plus),并做了大量重写和增强。
主要的修改点:
1. 完善脱敏注解
2. 增加对Gson和FastJson序列化组件的支持
3. 增加Spring MVC框架的HttpMessageConverter接口数据脱敏插件
4. 增加基于Logback框架的MessageConverter日志脱敏插件