add masking

This commit is contained in:
Looly 2024-10-10 23:45:30 +08:00
parent be3ee886c0
commit 3227ea0979
6 changed files with 587 additions and 264 deletions

View File

@ -16,8 +16,9 @@
package org.dromara.hutool.core.data;
import org.dromara.hutool.core.data.masking.MaskingManager;
import org.dromara.hutool.core.data.masking.MaskingType;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.CharUtil;
/**
* 数据脱敏Data Masking工具类对某些敏感信息比如身份证号手机号卡号姓名地址邮箱等 屏蔽敏感数据<br>
@ -44,74 +45,6 @@ import org.dromara.hutool.core.text.CharUtil;
*/
public class MaskingUtil {
/**
* 支持的脱敏类型枚举
*
* @author dazer and neusoft and qiaomu
*/
public enum MaskingType {
/**
* 用户id
*/
USER_ID,
/**
* 中文名
*/
CHINESE_NAME,
/**
* 身份证号
*/
ID_CARD,
/**
* 座机号
*/
FIXED_PHONE,
/**
* 手机号
*/
MOBILE_PHONE,
/**
* 地址
*/
ADDRESS,
/**
* 电子邮件
*/
EMAIL,
/**
* 密码
*/
PASSWORD,
/**
* 中国大陆车牌包含普通车辆新能源车辆
*/
CAR_LICENSE,
/**
* 银行卡
*/
BANK_CARD,
/**
* IPv4地址
*/
IPV4,
/**
* IPv6地址
*/
IPV6,
/**
* 定义了一个first_mask的规则只显示第一个字符
*/
FIRST_MASK,
/**
* 清空为null
*/
CLEAR_TO_NULL,
/**
* 清空为""
*/
CLEAR_TO_EMPTY
}
/**
* 脱敏使用默认的脱敏策略
* <pre>
@ -134,60 +67,8 @@ public class MaskingUtil {
* @author dazer and neusoft and qiaomu
* @since 5.6.2
*/
public static String masking(final CharSequence str, final MaskingType maskingType) {
if (StrUtil.isBlank(str)) {
return StrUtil.EMPTY;
}
String newStr = String.valueOf(str);
switch (maskingType) {
case USER_ID:
newStr = String.valueOf(userId());
break;
case CHINESE_NAME:
newStr = chineseName(String.valueOf(str));
break;
case ID_CARD:
newStr = idCardNum(String.valueOf(str), 1, 2);
break;
case FIXED_PHONE:
newStr = fixedPhone(String.valueOf(str));
break;
case MOBILE_PHONE:
newStr = mobilePhone(String.valueOf(str));
break;
case ADDRESS:
newStr = address(String.valueOf(str), 8);
break;
case EMAIL:
newStr = email(String.valueOf(str));
break;
case PASSWORD:
newStr = password(String.valueOf(str));
break;
case CAR_LICENSE:
newStr = carLicense(String.valueOf(str));
break;
case BANK_CARD:
newStr = bankCard(String.valueOf(str));
break;
case IPV4:
newStr = ipv4(String.valueOf(str));
break;
case IPV6:
newStr = ipv6(String.valueOf(str));
break;
case FIRST_MASK:
newStr = firstMask(String.valueOf(str));
break;
case CLEAR_TO_EMPTY:
newStr = clear();
break;
case CLEAR_TO_NULL:
newStr = clearToNull();
break;
default:
}
return newStr;
public static String masking(final MaskingType maskingType, final CharSequence str) {
return MaskingManager.getInstance().masking(maskingType.name(), str);
}
/**
@ -219,6 +100,16 @@ public class MaskingUtil {
return 0L;
}
/**
* 中文姓名只显示第一个汉字其他隐藏为2个星号比如**
*
* @param fullName 姓名
* @return 脱敏后的姓名
*/
public static String chineseName(final CharSequence fullName) {
return firstMask(fullName);
}
/**
* 定义了一个first_mask的规则只显示第一个字符<br>
* 脱敏前123456789脱敏后1********
@ -226,21 +117,8 @@ public class MaskingUtil {
* @param str 字符串
* @return 脱敏后的字符串
*/
public static String firstMask(final String str) {
if (StrUtil.isBlank(str)) {
return StrUtil.EMPTY;
}
return StrUtil.hide(str, 1, str.length());
}
/**
* 中文姓名只显示第一个汉字其他隐藏为2个星号比如**
*
* @param fullName 姓名
* @return 脱敏后的姓名
*/
public static String chineseName(final String fullName) {
return firstMask(fullName);
public static String firstMask(final CharSequence str) {
return MaskingManager.EMPTY.firstMask(str);
}
/**
@ -251,20 +129,8 @@ public class MaskingUtil {
* @param end 保留后面的end位数从1开始
* @return 脱敏后的身份证
*/
public static String idCardNum(final String idCardNum, final int front, final int end) {
//身份证不能为空
if (StrUtil.isBlank(idCardNum)) {
return StrUtil.EMPTY;
}
//需要截取的长度不能大于身份证号长度
if ((front + end) > idCardNum.length()) {
return StrUtil.EMPTY;
}
//需要截取的不能小于0
if (front < 0 || end < 0) {
return StrUtil.EMPTY;
}
return StrUtil.hide(idCardNum, front, idCardNum.length() - end);
public static String idCardNum(final CharSequence idCardNum, final int front, final int end) {
return MaskingManager.EMPTY.idCardNum(idCardNum, front, end);
}
/**
@ -273,11 +139,8 @@ public class MaskingUtil {
* @param num 固定电话
* @return 脱敏后的固定电话
*/
public static String fixedPhone(final String num) {
if (StrUtil.isBlank(num)) {
return StrUtil.EMPTY;
}
return StrUtil.hide(num, 4, num.length() - 2);
public static String fixedPhone(final CharSequence num) {
return MaskingManager.EMPTY.fixedPhone(num);
}
/**
@ -286,11 +149,8 @@ public class MaskingUtil {
* @param num 移动电话
* @return 脱敏后的移动电话
*/
public static String mobilePhone(final String num) {
if (StrUtil.isBlank(num)) {
return StrUtil.EMPTY;
}
return StrUtil.hide(num, 3, num.length() - 4);
public static String mobilePhone(final CharSequence num) {
return MaskingManager.EMPTY.mobilePhone(num);
}
/**
@ -300,12 +160,8 @@ public class MaskingUtil {
* @param sensitiveSize 敏感信息长度
* @return 脱敏后的家庭地址
*/
public static String address(final String address, final int sensitiveSize) {
if (StrUtil.isBlank(address)) {
return StrUtil.EMPTY;
}
final int length = address.length();
return StrUtil.hide(address, length - sensitiveSize, length);
public static String address(final CharSequence address, final int sensitiveSize) {
return MaskingManager.EMPTY.address(address, sensitiveSize);
}
/**
@ -314,28 +170,23 @@ public class MaskingUtil {
* @param email 邮箱
* @return 脱敏后的邮箱
*/
public static String email(final String email) {
if (StrUtil.isBlank(email)) {
return StrUtil.EMPTY;
}
final int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email;
}
return StrUtil.hide(email, 1, index);
public static String email(final CharSequence email) {
return MaskingManager.EMPTY.email(email);
}
/**
* 密码密码的全部字符都用*代替比如******
* 密码密码的全部字符都用*代替比如******<br>
* 密码位数不能被猜测因此固定10位
*
* @param password 密码
* @return 脱敏后的密码
*/
public static String password(final String password) {
public static String password(final CharSequence password) {
if (StrUtil.isBlank(password)) {
return StrUtil.EMPTY;
}
return StrUtil.repeat('*', password.length());
// 密码位数不能被猜测因此固定10位
return StrUtil.repeat('*', 10);
}
/**
@ -349,18 +200,8 @@ public class MaskingUtil {
* @param carLicense 完整的车牌号
* @return 脱敏后的车牌
*/
public static String carLicense(String carLicense) {
if (StrUtil.isBlank(carLicense)) {
return StrUtil.EMPTY;
}
// 普通车牌
if (carLicense.length() == 7) {
carLicense = StrUtil.hide(carLicense, 3, 6);
} else if (carLicense.length() == 8) {
// 新能源车牌
carLicense = StrUtil.hide(carLicense, 3, 7);
}
return carLicense;
public static String carLicense(final CharSequence carLicense) {
return MaskingManager.EMPTY.carLicense(carLicense);
}
/**
@ -371,29 +212,8 @@ public class MaskingUtil {
* @return 脱敏之后的银行卡号
* @since 5.6.3
*/
public static String bankCard(String bankCardNo) {
if (StrUtil.isBlank(bankCardNo)) {
return bankCardNo;
}
bankCardNo = StrUtil.cleanBlank(bankCardNo);
if (bankCardNo.length() < 9) {
return bankCardNo;
}
final int length = bankCardNo.length();
final int endLength = length % 4 == 0 ? 4 : length % 4;
final int midLength = length - 4 - endLength;
final StringBuilder buf = new StringBuilder();
buf.append(bankCardNo, 0, 4);
for (int i = 0; i < midLength; ++i) {
if (i % 4 == 0) {
buf.append(CharUtil.SPACE);
}
buf.append('*');
}
buf.append(CharUtil.SPACE).append(bankCardNo, length - endLength, length);
return buf.toString();
public static String bankCard(final CharSequence bankCardNo) {
return MaskingManager.EMPTY.bankCard(bankCardNo);
}
/**
@ -402,8 +222,8 @@ public class MaskingUtil {
* @param ipv4 IPv4地址
* @return 脱敏后的地址
*/
public static String ipv4(final String ipv4) {
return StrUtil.subBefore(ipv4, '.', false) + ".*.*.*";
public static String ipv4(final CharSequence ipv4) {
return MaskingManager.EMPTY.ipv4(ipv4);
}
/**
@ -412,7 +232,7 @@ public class MaskingUtil {
* @param ipv6 IPv6地址
* @return 脱敏后的地址
*/
public static String ipv6(final String ipv6) {
return StrUtil.subBefore(ipv6, ':', false) + ":*:*:*:*:*:*:*";
public static String ipv6(final CharSequence ipv6) {
return MaskingManager.EMPTY.ipv6(ipv6);
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.core.data.masking;
/**
* 脱敏处理器用于自定义脱敏规则
*
*/
@FunctionalInterface
public interface MaskingHandler {
/**
* 处理传入的数据字符串经过脱敏逻辑后返回处理后的值
*
* @param value 待处理的值
* @return 处理后的值
*/
String handle(CharSequence value);
}

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.core.data.masking;
import org.dromara.hutool.core.text.CharUtil;
import org.dromara.hutool.core.text.StrUtil;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.dromara.hutool.core.data.masking.MaskingType.*;
/**
* 脱敏管理器用于管理所有脱敏处理器使用方式有三种
* <ul>
* <li>全局默认使用{@link MaskingManager#getInstance()}带有预定义的脱敏方法</li>
* <li>自定义默认使用{@link MaskingManager#ofDefault(char)}可以自定义脱敏字符带有预定义的脱敏方法</li>
* <li>自定义使用{@link #MaskingManager(Map, char)}构造不带有默认规则</li>
* </ul>
*
* @author Looly
*/
public class MaskingManager {
/**
* 默认的脱敏字符*
*/
public static final char DEFAULT_MASK_CHAR = '*';
/**
* 类级的内部类也就是静态的成员式内部类该内部类的实例与外部类的实例 没有绑定关系而且只有被调用到才会装载从而实现了延迟加载
*/
private static class SingletonHolder {
/**
* 静态初始化器由JVM来保证线程安全
*/
private static final MaskingManager INSTANCE = registerDefault(DEFAULT_MASK_CHAR);
}
/**
* 空脱敏管理器用于不处理任何数据的情况
*/
public static final MaskingManager EMPTY = new MaskingManager(null);
/**
* 获得单例的 MaskingManager
*
* @return MaskingManager
*/
public static MaskingManager getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 创建默认的脱敏管理器通过给定的脱敏字符提供默认的脱敏规则
*
* @param maskChar 脱敏字符默认为*
* @return 默认的脱敏管理器
*/
public static MaskingManager ofDefault(final char maskChar) {
return registerDefault(maskChar);
}
private final Map<String, MaskingHandler> handlerMap;
private final char maskChar;
/**
* 构造
*
* @param handlerMap 脱敏处理器Map如果应用于单例则需要传入线程安全的Map
*/
public MaskingManager(final Map<String, MaskingHandler> handlerMap) {
this(handlerMap, DEFAULT_MASK_CHAR);
}
/**
* 构造
*
* @param handlerMap 脱敏处理器Map如果应用于单例则需要传入线程安全的Map
* @param maskChar 默认的脱敏字符默认为*
*/
public MaskingManager(final Map<String, MaskingHandler> handlerMap, final char maskChar) {
this.handlerMap = handlerMap;
this.maskChar = maskChar;
}
/**
* 注册一个脱敏处理器
*
* @param type 类型
* @param handler 脱敏处理器
* @return this
*/
public MaskingManager register(final String type, final MaskingHandler handler) {
this.handlerMap.put(type, handler);
return this;
}
/**
* 脱敏处理<br>
* 如果没有指定的脱敏处理器则返回{@code null}
*
* @param type 类型
* @param value 待脱敏值
* @return 脱敏后的值
*/
public String masking(String type, final CharSequence value) {
if (StrUtil.isEmpty(type)) {
type = CLEAR_TO_NULL.name();
}
final MaskingHandler handler = handlerMap.get(type);
return null == handler ? null : handler.handle(value);
}
/**
* 默认的脱敏处理器注册
*
* @param maskChar 默认的脱敏字符默认为*
* @return 默认的脱敏处理器注册
*/
private static MaskingManager registerDefault(final char maskChar) {
final MaskingManager manager = new MaskingManager(
new ConcurrentHashMap<>(15, 1), maskChar);
manager.register(USER_ID.name(), (str) -> "0");
manager.register(CHINESE_NAME.name(), manager::firstMask);
manager.register(ID_CARD.name(), (str) -> manager.idCardNum(str, 1, 2));
manager.register(FIXED_PHONE.name(), manager::fixedPhone);
manager.register(MOBILE_PHONE.name(), manager::mobilePhone);
manager.register(ADDRESS.name(), (str) -> manager.address(str, 8));
manager.register(EMAIL.name(), manager::email);
manager.register(PASSWORD.name(), manager::password);
manager.register(CAR_LICENSE.name(), manager::carLicense);
manager.register(BANK_CARD.name(), manager::bankCard);
manager.register(IPV4.name(), manager::ipv4);
manager.register(IPV6.name(), manager::ipv6);
manager.register(FIRST_MASK.name(), manager::firstMask);
manager.register(CLEAR_TO_EMPTY.name(), (str) -> StrUtil.EMPTY);
manager.register(CLEAR_TO_NULL.name(), (str) -> null);
return manager;
}
/**
* 定义了一个first_mask的规则只显示第一个字符<br>
* 脱敏前123456789脱敏后1********
*
* @param str 字符串
* @return 脱敏后的字符串
*/
public String firstMask(final CharSequence str) {
if (StrUtil.isBlank(str)) {
return StrUtil.EMPTY;
}
return StrUtil.replaceByCodePoint(str, 1, str.length(), maskChar);
}
/**
* 身份证号前1位 和后2位
*
* @param idCardNum 身份证
* @param front 保留前面的front位数从1开始
* @param end 保留后面的end位数从1开始
* @return 脱敏后的身份证
*/
public String idCardNum(final CharSequence idCardNum, final int front, final int end) {
//身份证不能为空
if (StrUtil.isBlank(idCardNum)) {
return StrUtil.EMPTY;
}
//需要截取的长度不能大于身份证号长度
if ((front + end) > idCardNum.length()) {
return StrUtil.EMPTY;
}
//需要截取的不能小于0
if (front < 0 || end < 0) {
return StrUtil.EMPTY;
}
return StrUtil.replaceByCodePoint(idCardNum, front, idCardNum.length() - end, maskChar);
}
/**
* 固定电话 前四位后两位
*
* @param num 固定电话
* @return 脱敏后的固定电话
*/
public String fixedPhone(final CharSequence num) {
if (StrUtil.isBlank(num)) {
return StrUtil.EMPTY;
}
return StrUtil.replaceByCodePoint(num, 4, num.length() - 2, maskChar);
}
/**
* 手机号码前三位后4位其他隐藏比如135****2210
*
* @param num 移动电话
* @return 脱敏后的移动电话
*/
public String mobilePhone(final CharSequence num) {
if (StrUtil.isBlank(num)) {
return StrUtil.EMPTY;
}
return StrUtil.replaceByCodePoint(num, 3, num.length() - 4, maskChar);
}
/**
* 地址只显示到地区不显示详细地址比如北京市海淀区****
*
* @param address 家庭住址
* @param sensitiveSize 敏感信息长度
* @return 脱敏后的家庭地址
*/
public String address(final CharSequence address, final int sensitiveSize) {
if (StrUtil.isBlank(address)) {
return StrUtil.EMPTY;
}
final int length = address.length();
return StrUtil.replaceByCodePoint(address, length - sensitiveSize, length, maskChar);
}
/**
* 电子邮箱邮箱前缀仅显示第一个字母前缀其他隐藏用星号代替@及后面的地址显示比如d**@126.com
*
* @param email 邮箱
* @return 脱敏后的邮箱
*/
public String email(final CharSequence email) {
if (StrUtil.isBlank(email)) {
return StrUtil.EMPTY;
}
final int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email.toString();
}
return StrUtil.replaceByCodePoint(email, 1, index, maskChar);
}
/**
* 密码密码的全部字符都用定义的脱敏字符*代替比如******<br>
* 密码位数不能被猜测因此固定10位
*
* @param password 密码
* @return 脱敏后的密码
*/
public String password(final CharSequence password) {
if (StrUtil.isBlank(password)) {
return StrUtil.EMPTY;
}
// 密码位数不能被猜测因此固定10位
return StrUtil.repeat(maskChar, 10);
}
/**
* 中国车牌车牌中间用脱敏字符*)代替
* eg1null - ""
* eg1"" - ""
* eg3苏D40000 - 苏D4***0
* eg4陕A12345D - 陕A1****D
* eg5京A123 - 京A123 如果是错误的车牌不处理
*
* @param carLicense 完整的车牌号
* @return 脱敏后的车牌
*/
public String carLicense(CharSequence carLicense) {
if (StrUtil.isBlank(carLicense)) {
return StrUtil.EMPTY;
}
// 普通车牌
if (carLicense.length() == 7) {
carLicense = StrUtil.replaceByCodePoint(carLicense, 3, 6, maskChar);
} else if (carLicense.length() == 8) {
// 新能源车牌
carLicense = StrUtil.replaceByCodePoint(carLicense, 3, 7, maskChar);
}
return carLicense.toString();
}
/**
* 银行卡号脱敏
* eg: 1101 **** **** **** 3256
*
* @param bankCardNo 银行卡号
* @return 脱敏之后的银行卡号
*/
public String bankCard(CharSequence bankCardNo) {
if (StrUtil.isBlank(bankCardNo)) {
return StrUtil.toStringOrNull(bankCardNo);
}
bankCardNo = StrUtil.cleanBlank(bankCardNo);
if (bankCardNo.length() < 9) {
return bankCardNo.toString();
}
final int length = bankCardNo.length();
final int endLength = length % 4 == 0 ? 4 : length % 4;
final int midLength = length - 4 - endLength;
final StringBuilder buf = new StringBuilder();
buf.append(bankCardNo, 0, 4);
for (int i = 0; i < midLength; ++i) {
if (i % 4 == 0) {
buf.append(CharUtil.SPACE);
}
buf.append(maskChar);
}
buf.append(CharUtil.SPACE).append(bankCardNo, length - endLength, length);
return buf.toString();
}
/**
* IPv4脱敏脱敏前192.0.2.1脱敏后192.*.*.*
*
* @param ipv4 IPv4地址
* @return 脱敏后的地址
*/
public String ipv4(final CharSequence ipv4) {
return StrUtil.subBefore(ipv4, '.', false) + StrUtil.repeat("." + maskChar, 3);
}
/**
* IPv6脱敏脱敏前2001:0db8:86a3:08d3:1319:8a2e:0370:7344脱敏后2001:*:*:*:*:*:*:*
*
* @param ipv6 IPv6地址
* @return 脱敏后的地址
*/
public String ipv6(final CharSequence ipv6) {
return StrUtil.subBefore(ipv6, ':', false) + StrUtil.repeat(":" + maskChar, 7);
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.core.data.masking;
/**
* 支持的脱敏类型枚举
*
* @author dazer and neusoft and qiaomu
*/
public enum MaskingType {
/**
* 用户id
*/
USER_ID,
/**
* 中文名
*/
CHINESE_NAME,
/**
* 身份证号
*/
ID_CARD,
/**
* 座机号
*/
FIXED_PHONE,
/**
* 手机号
*/
MOBILE_PHONE,
/**
* 地址
*/
ADDRESS,
/**
* 电子邮件
*/
EMAIL,
/**
* 密码
*/
PASSWORD,
/**
* 中国大陆车牌包含普通车辆新能源车辆
*/
CAR_LICENSE,
/**
* 银行卡
*/
BANK_CARD,
/**
* IPv4地址
*/
IPV4,
/**
* IPv6地址
*/
IPV6,
/**
* 定义了一个first_mask的规则只显示第一个字符
*/
FIRST_MASK,
/**
* 清空为null
*/
CLEAR_TO_NULL,
/**
* 清空为""
*/
CLEAR_TO_EMPTY
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 数据脱敏提供各种数据类型字符串数字等的脱敏方法
*
* @author looly
*/
package org.dromara.hutool.core.data.masking;

View File

@ -16,9 +16,13 @@
package org.dromara.hutool.core.data;
import org.dromara.hutool.core.data.masking.MaskingManager;
import org.dromara.hutool.core.data.masking.MaskingType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* 脱敏工具类 MaskingUtil 安全测试
*
@ -29,94 +33,108 @@ public class MaskingUtilTest {
@Test
public void maskingTest() {
Assertions.assertEquals("", MaskingUtil.masking("100", MaskingUtil.MaskingType.CLEAR_TO_EMPTY));
Assertions.assertNull(MaskingUtil.masking("100", MaskingUtil.MaskingType.CLEAR_TO_NULL));
assertEquals("", MaskingUtil.masking(MaskingType.CLEAR_TO_EMPTY, "100"));
Assertions.assertNull(MaskingUtil.masking(MaskingType.CLEAR_TO_NULL, "100"));
Assertions.assertEquals("0", MaskingUtil.masking("100", MaskingUtil.MaskingType.USER_ID));
Assertions.assertEquals("段**", MaskingUtil.masking("段正淳", MaskingUtil.MaskingType.CHINESE_NAME));
Assertions.assertEquals("5***************1X", MaskingUtil.masking("51343620000320711X", MaskingUtil.MaskingType.ID_CARD));
Assertions.assertEquals("0915*****79", MaskingUtil.masking("09157518479", MaskingUtil.MaskingType.FIXED_PHONE));
Assertions.assertEquals("180****1999", MaskingUtil.masking("18049531999", MaskingUtil.MaskingType.MOBILE_PHONE));
Assertions.assertEquals("北京市海淀区马********", MaskingUtil.masking("北京市海淀区马连洼街道289号", MaskingUtil.MaskingType.ADDRESS));
Assertions.assertEquals("d*************@gmail.com.cn", MaskingUtil.masking("duandazhi-jack@gmail.com.cn", MaskingUtil.MaskingType.EMAIL));
Assertions.assertEquals("**********", MaskingUtil.masking("1234567890", MaskingUtil.MaskingType.PASSWORD));
assertEquals("0", MaskingUtil.masking(MaskingType.USER_ID, "100"));
assertEquals("段**", MaskingUtil.masking(MaskingType.CHINESE_NAME, "段正淳"));
assertEquals("5***************1X", MaskingUtil.masking(MaskingType.ID_CARD, "51343620000320711X"));
assertEquals("0915*****79", MaskingUtil.masking(MaskingType.FIXED_PHONE, "09157518479"));
assertEquals("180****1999", MaskingUtil.masking(MaskingType.MOBILE_PHONE, "18049531999"));
assertEquals("北京市海淀区马********", MaskingUtil.masking(MaskingType.ADDRESS, "北京市海淀区马连洼街道289号"));
assertEquals("d*************@gmail.com.cn", MaskingUtil.masking(MaskingType.EMAIL, "duandazhi-jack@gmail.com.cn"));
assertEquals("**********", MaskingUtil.masking(MaskingType.PASSWORD, "1234567890"));
assertEquals("**********", MaskingUtil.masking(MaskingType.PASSWORD, "123"));
assertEquals("1101 **** **** **** 3256", MaskingUtil.masking(MaskingType.BANK_CARD, "11011111222233333256"));
assertEquals("6227 **** **** **** 123", MaskingUtil.masking(MaskingType.BANK_CARD, "6227880100100105123"));
assertEquals("192.*.*.*", MaskingUtil.masking(MaskingType.IPV4, "192.168.1.1"));
assertEquals("2001:*:*:*:*:*:*:*", MaskingUtil.masking(MaskingType.IPV6, "2001:0db8:86a3:08d3:1319:8a2e:0370:7344"));
}
Assertions.assertEquals("0", MaskingUtil.masking("100", MaskingUtil.MaskingType.USER_ID));
Assertions.assertEquals("段**", MaskingUtil.masking("段正淳", MaskingUtil.MaskingType.CHINESE_NAME));
Assertions.assertEquals("5***************1X", MaskingUtil.masking("51343620000320711X", MaskingUtil.MaskingType.ID_CARD));
Assertions.assertEquals("0915*****79", MaskingUtil.masking("09157518479", MaskingUtil.MaskingType.FIXED_PHONE));
Assertions.assertEquals("180****1999", MaskingUtil.masking("18049531999", MaskingUtil.MaskingType.MOBILE_PHONE));
Assertions.assertEquals("北京市海淀区马********", MaskingUtil.masking("北京市海淀区马连洼街道289号", MaskingUtil.MaskingType.ADDRESS));
Assertions.assertEquals("d*************@gmail.com.cn", MaskingUtil.masking("duandazhi-jack@gmail.com.cn", MaskingUtil.MaskingType.EMAIL));
Assertions.assertEquals("**********", MaskingUtil.masking("1234567890", MaskingUtil.MaskingType.PASSWORD));
Assertions.assertEquals("1101 **** **** **** 3256", MaskingUtil.masking("11011111222233333256", MaskingUtil.MaskingType.BANK_CARD));
Assertions.assertEquals("6227 **** **** **** 123", MaskingUtil.masking("6227880100100105123", MaskingUtil.MaskingType.BANK_CARD));
Assertions.assertEquals("192.*.*.*", MaskingUtil.masking("192.168.1.1", MaskingUtil.MaskingType.IPV4));
Assertions.assertEquals("2001:*:*:*:*:*:*:*", MaskingUtil.masking("2001:0db8:86a3:08d3:1319:8a2e:0370:7344", MaskingUtil.MaskingType.IPV6));
@Test
public void maskingWithMaskCharTest() {
final MaskingManager manager = MaskingManager.ofDefault('#');
assertEquals("", manager.masking(MaskingType.CLEAR_TO_EMPTY.name(), "100"));
Assertions.assertNull(manager.masking(MaskingType.CLEAR_TO_NULL.name(), "100"));
assertEquals("0", manager.masking(MaskingType.USER_ID.name(), "100"));
assertEquals("段##", manager.masking(MaskingType.CHINESE_NAME.name(), "段正淳"));
assertEquals("5###############1X", manager.masking(MaskingType.ID_CARD.name(), "51343620000320711X"));
assertEquals("0915#####79", manager.masking(MaskingType.FIXED_PHONE.name(), "09157518479"));
assertEquals("180####1999", manager.masking(MaskingType.MOBILE_PHONE.name(), "18049531999"));
assertEquals("北京市海淀区马########", manager.masking(MaskingType.ADDRESS.name(), "北京市海淀区马连洼街道289号"));
assertEquals("d#############@gmail.com.cn", manager.masking(MaskingType.EMAIL.name(), "duandazhi-jack@gmail.com.cn"));
assertEquals("##########", manager.masking(MaskingType.PASSWORD.name(), "1234567890"));
assertEquals("##########", manager.masking(MaskingType.PASSWORD.name(), "123"));
assertEquals("1101 #### #### #### 3256", manager.masking(MaskingType.BANK_CARD.name(), "11011111222233333256"));
assertEquals("6227 #### #### #### 123", manager.masking(MaskingType.BANK_CARD.name(), "6227880100100105123"));
assertEquals("192.#.#.#", manager.masking(MaskingType.IPV4.name(), "192.168.1.1"));
assertEquals("2001:#:#:#:#:#:#:#", manager.masking(MaskingType.IPV6.name(), "2001:0db8:86a3:08d3:1319:8a2e:0370:7344"));
}
@Test
public void userIdTest() {
Assertions.assertEquals(Long.valueOf(0L), MaskingUtil.userId());
assertEquals(Long.valueOf(0L), MaskingUtil.userId());
}
@Test
public void chineseNameTest() {
Assertions.assertEquals("段**", MaskingUtil.chineseName("段正淳"));
assertEquals("段**", MaskingUtil.chineseName("段正淳"));
}
@Test
public void idCardNumTest() {
Assertions.assertEquals("5***************1X", MaskingUtil.idCardNum("51343620000320711X", 1, 2));
assertEquals("5***************1X", MaskingUtil.idCardNum("51343620000320711X", 1, 2));
}
@Test
public void fixedPhoneTest() {
Assertions.assertEquals("0915*****79", MaskingUtil.fixedPhone("09157518479"));
assertEquals("0915*****79", MaskingUtil.fixedPhone("09157518479"));
}
@Test
public void mobilePhoneTest() {
Assertions.assertEquals("180****1999", MaskingUtil.mobilePhone("18049531999"));
assertEquals("180****1999", MaskingUtil.mobilePhone("18049531999"));
}
@Test
public void addressTest() {
Assertions.assertEquals("北京市海淀区马连洼街*****", MaskingUtil.address("北京市海淀区马连洼街道289号", 5));
Assertions.assertEquals("***************", MaskingUtil.address("北京市海淀区马连洼街道289号", 50));
Assertions.assertEquals("北京市海淀区马连洼街道289号", MaskingUtil.address("北京市海淀区马连洼街道289号", 0));
Assertions.assertEquals("北京市海淀区马连洼街道289号", MaskingUtil.address("北京市海淀区马连洼街道289号", -1));
assertEquals("北京市海淀区马连洼街*****", MaskingUtil.address("北京市海淀区马连洼街道289号", 5));
assertEquals("***************", MaskingUtil.address("北京市海淀区马连洼街道289号", 50));
assertEquals("北京市海淀区马连洼街道289号", MaskingUtil.address("北京市海淀区马连洼街道289号", 0));
assertEquals("北京市海淀区马连洼街道289号", MaskingUtil.address("北京市海淀区马连洼街道289号", -1));
}
@Test
public void emailTest() {
Assertions.assertEquals("d********@126.com", MaskingUtil.email("duandazhi@126.com"));
Assertions.assertEquals("d********@gmail.com.cn", MaskingUtil.email("duandazhi@gmail.com.cn"));
Assertions.assertEquals("d*************@gmail.com.cn", MaskingUtil.email("duandazhi-jack@gmail.com.cn"));
assertEquals("d********@126.com", MaskingUtil.email("duandazhi@126.com"));
assertEquals("d********@gmail.com.cn", MaskingUtil.email("duandazhi@gmail.com.cn"));
assertEquals("d*************@gmail.com.cn", MaskingUtil.email("duandazhi-jack@gmail.com.cn"));
}
@Test
public void passwordTest() {
Assertions.assertEquals("**********", MaskingUtil.password("1234567890"));
assertEquals("**********", MaskingUtil.password("1234567890"));
}
@Test
public void carLicenseTest() {
Assertions.assertEquals("", MaskingUtil.carLicense(null));
Assertions.assertEquals("", MaskingUtil.carLicense(""));
Assertions.assertEquals("苏D4***0", MaskingUtil.carLicense("苏D40000"));
Assertions.assertEquals("陕A1****D", MaskingUtil.carLicense("陕A12345D"));
Assertions.assertEquals("京A123", MaskingUtil.carLicense("京A123"));
assertEquals("", MaskingUtil.carLicense(null));
assertEquals("", MaskingUtil.carLicense(""));
assertEquals("苏D4***0", MaskingUtil.carLicense("苏D40000"));
assertEquals("陕A1****D", MaskingUtil.carLicense("陕A12345D"));
assertEquals("京A123", MaskingUtil.carLicense("京A123"));
}
@Test
public void bankCardTest() {
Assertions.assertNull(MaskingUtil.bankCard(null));
Assertions.assertEquals("", MaskingUtil.bankCard(""));
Assertions.assertEquals("1234 **** **** **** **** 9", MaskingUtil.bankCard("1234 2222 3333 4444 6789 9"));
Assertions.assertEquals("1234 **** **** **** **** 91", MaskingUtil.bankCard("1234 2222 3333 4444 6789 91"));
Assertions.assertEquals("1234 **** **** **** 6789", MaskingUtil.bankCard("1234 2222 3333 4444 6789"));
Assertions.assertEquals("1234 **** **** **** 678", MaskingUtil.bankCard("1234 2222 3333 4444 678"));
assertEquals("", MaskingUtil.bankCard(""));
assertEquals("1234 **** **** **** **** 9", MaskingUtil.bankCard("1234 2222 3333 4444 6789 9"));
assertEquals("1234 **** **** **** **** 91", MaskingUtil.bankCard("1234 2222 3333 4444 6789 91"));
assertEquals("1234 **** **** **** 6789", MaskingUtil.bankCard("1234 2222 3333 4444 6789"));
assertEquals("1234 **** **** **** 678", MaskingUtil.bankCard("1234 2222 3333 4444 678"));
}
}