程序设计的所有原则和方法论都是追求一件事——简单——功能简单、依赖简单、修改简单、理解简单。因为只有简单才好用,简单才好维护。因此,不应该以评论艺术品的眼光来评价程序设计是否优秀,程序设计的艺术不在于有多复杂多深沉,而在于能用多简单的方式实现多复杂的业务需求;不在于只有少数人能理解,而在于能让更多人理解。
给大家介绍一个java应用中简单强大的脱敏处理工具。
简单之处: 在于研发只需要通过其工厂方法接口MaskHandlerFactory
创建脱敏处理器IMaskHandler
强大之处:能够满足大多数场景,不限语言。比如中国人不同长度的姓名脱敏、外国人姓名脱敏、邮箱@前后个性化脱敏等。
maven依赖如下:
<dependency>
<groupId>io.github.chyohn.mask</groupId>
<artifactId>mask</artifactId>
<version>1.0.0-RELEASE</version>
</dependency>
下面给大家介绍它的使用场景
使用场景
1. 左边n位脱敏
左边脱敏位数 | 字符串 | 脱敏输出 |
---|---|---|
1 | abcd | *bcd |
2 | abcdef | **cdef |
如下面模糊左边2个字符
void maskLeft() {
IMaskHandler maskHandler = MaskHandlerFactory.maskLeft(2);
Assertions.assertEquals(maskHandler.handle("司马相如"), "**相如");
}
2. 右边n位脱敏
右边脱敏位数 | 字符串 | 脱敏输出 |
---|---|---|
1 | abcd | abc* |
2 | abcdef | abcd** |
如下面模糊字符串中右边2个字符
void maskRight() {
IMaskHandler maskHandler = MaskHandlerFactory.maskRight(2);
Assertions.assertEquals(maskHandler.handle("司马相如"), "司马**");
}
3. 两边n位脱敏
两边脱敏位数 | 字符串 | 脱敏输出 |
---|---|---|
1 | abcd | *bc* |
2 | abcdef | **cd** |
如下面示例模糊字符串中两边1个字符
void maskMargin() { // 两边n位脱敏
IMaskHandler maskHandler = MaskHandlerFactory.maskMargin(1);
Assertions.assertEquals(maskHandler.handle("司马相如"), "*马相*");
}
4. 左边n位脱敏右边m位脱敏
左边脱敏位数 | 右边脱敏位数 | 字符串 | 脱敏输出 |
---|---|---|---|
1 | 2 | abcd | *b** |
1 | 2 | abc | *** |
2 | 3 | abcefg | **c*** |
如下面示例,模糊字符串中左边1位和右边2位
void maskOuter() { // 左边n位脱敏右边m位脱敏
IMaskHandler maskHandler = MaskHandlerFactory.maskOuter(1, 2);
Assertions.assertEquals(maskHandler.handle("司马相如"), "*马**");
}
5. 中间脱敏,保留两边n位
两边保留位数 | 字符串 | 脱敏输出 |
---|---|---|
1 | abcd | a**d |
2 | ab | ** |
2 | abcdef | ab**ef |
如下面示例,保留字符串两边1个字符
void reserveMargin() { // 中间脱敏,保留两边n位
IMaskHandler maskHandler = MaskHandlerFactory.reserveMargin(1);
Assertions.assertEquals(maskHandler.handle("司马相如"), "司**如");
}
6. 中间脱敏,保留左边n位和右边m位
左边保留位数 | 右边保留位数 | 字符串 | 脱敏输出 |
---|---|---|---|
1 | 2 | ab | ** |
1 | 2 | abcd | a*cd |
1 | 2 | abcde | a**de |
如下面示例,保留字符串左边1个字符和右边2个字符
void reserveOuter() { // 中间脱敏,保留左边n位右边m位
IMaskHandler maskHandler = MaskHandlerFactory.reserveOuter(1, 2);
Assertions.assertEquals(maskHandler.handle("司马相如"), "司*相如");
}
7. 指定脱敏占位符
默认的占位符为*
,可以指定自定义的,比如^_^
是不是特别有意思,见下面示例
void maskRightWithNewMaskStr() { // 指定脱敏占位符
IMaskHandler maskHandler = MaskHandlerFactory.maskRight(2).setMaskStr("^_^");
Assertions.assertEquals(maskHandler.handle("司马相如"), "司马^_^^_^");
}
8. 指定固定数量的脱敏占位符
占位符太多,看上去也不好,可以指定总的占位符数量,见下面示例
void maskRightWithNewMaskStrNum() { // 指定脱敏占位符, 固定占位符个数
IMaskHandler maskHandler = MaskHandlerFactory.maskRight(2)
.setMaskStr("^_^")
.setMaskLength(1);
Assertions.assertEquals(maskHandler.handle("司马相如"), "司马^_^");
}
复杂场景
前面都是比较简单的场景,对于复杂的场景也支持,不外乎就是前面简单场景的各种随意组合,下面列举了比较典型的例子。
1. 不同长度的字符串脱敏方式不同
对于中文姓名,有2个字符串、3个字符、4个字符以上,对于不同中文个数不同的姓名脱敏方式也不同
- 2个中文的姓名保留姓氏
- 3个中文的姓名,模糊中间的中文
- 4个中文以上的姓名,保留两边各1个中文
上面中文姓名脱敏实现如下
void maskSize() { // 不同长度的字符串脱敏方式不同
// 定义2个中文姓名脱敏方式,保留左边姓氏
IMaskHandler maskHandlerFor2 = MaskHandlerFactory.reserveLeft(1);
// 定义3个中文以上的姓名脱敏方式,保留两边1个中文
IMaskHandler maskHandlerFor3 = MaskHandlerFactory.reserveMargin(1);
// 使用长度选择器
IMaskHandler maskHandler = MaskHandlerFactory.sizeSelector()
.addHandler(maskHandlerFor2, 2) // 2个中文
.addHandler(maskHandlerFor3, 3); // 3个中文以上
Assertions.assertEquals(maskHandler.handle("乔峰"), "乔*");
Assertions.assertEquals(maskHandler.handle("韦小宝"), "韦*宝");
Assertions.assertEquals(maskHandler.handle("司马相如"), "司**如");
}
2. 同个字符串中不同部分脱敏方式不同
对于邮箱@
前后脱敏不一样的需求,比如
@
左边的字符串只保留左边1个字符,其它全部脱敏@
右边部分的域名名称完全脱敏,保留.
后面的字符,如sina.com
脱敏为*.com
实现示例如下:
void maskPartSep() { // 同个字符串中不同部分脱敏方式不同,分隔符
// @左边的字符串只保留左边1个字符,其它全部脱敏
IMaskHandler left = MaskHandlerFactory.reserveLeft(1);
// `@`右边部分的域名名称完全脱敏,保留`.`后面的字符,如`sina.com`脱敏为`*.com`
IMaskHandler right = MaskHandlerFactory.reserveRight(1).setSeparator(".");
// 使用‘@’分隔字符串,组合左右两个脱敏处理器
IMaskHandler maskHandler = MaskHandlerFactory.group("@")
.addHandler(left, right); // 分割后的字符串数组, 第一个字符串用left脱敏,第二个字符串用right脱敏
Assertions.assertEquals(maskHandler.handle("cdef@sina.com"), "c***@*.com");
}
上面示例中right
脱敏对象的定义使用了.
分隔符,它的作用是把字符串分割为字符串数组,脱敏处理器不再以字符为最小单位做脱敏,
而是按数组元素为最小单位进行脱敏,因此,它会保留sina.com
中.
后面的整个com
,而不只是m
字符;而sina
作为分割后的数组元素,就只用1个占位符*
替换。
3. 英文姓名的脱敏
前面的脱敏方式都是已单个字符为最小单位进行脱敏,对于英文可能需要以单词为最小单位做脱敏,比如英文姓名。
下面我们假设英文姓名中的单词都是已空格分割,它的脱敏规则假设如下:(和前面中文姓名脱敏规则一样)
- 2个单词的姓名保留姓氏
- 3个单词的姓名,模糊中间的单词
- 4个单词以上的姓名,保留两边各1个单词
示例如下
void maskSizeEnglishName() {
// 使用空格分割,定义2个单词姓名脱敏方式,保留右边姓氏
IMaskHandler maskHandlerFor2 = MaskHandlerFactory.reserveRight(1).setSeparator(" ");
Assertions.assertEquals(maskHandlerFor2.handle("Michael Jordan"), "* Jordan");
// 使用空格分割,定义3个单词以上的姓名脱敏方式,保留两边1个单词
IMaskHandler maskHandlerFor3 = MaskHandlerFactory.reserveMargin(1).setSeparator(" ");
Assertions.assertEquals(maskHandlerFor3.handle("Michael Jeffrey Jordan"), "Michael * Jordan");
// 使用空格分割后,使用长度选择器
IMaskHandler maskHandler = MaskHandlerFactory.sizeSelector(" ")
.addHandler(maskHandlerFor2, 2) // 2个单词
.addHandler(maskHandlerFor3, 3); // 3个单词以上
Assertions.assertEquals(maskHandler.handle("Michael Jordan"), "* Jordan");
Assertions.assertEquals(maskHandler.handle("Michael Jeffrey Jordan"), "Michael * Jordan");
}
其它
更多可以见其github仓库地址:https://github.com/chyohn/mask