diff --git a/CHANGELOG.md b/CHANGELOG.md index 3066551a7..73018e528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,13 @@ ------------------------------------------------------------------------------------------------------------- -# 5.6.2 (2021-03-20) +# 5.6.2 (2021-03-21) ### 新特性 * 【core 】 Validator增加车架号(车辆识别码)验证、驾驶证(驾驶证档案编号)的正则校验(pr#280@Gitee) * 【core 】 CopyOptions增加propertiesFilter(pr#281@Gitee) * 【extra 】 增加Wit模板引擎支持 +* 【core 】 增加DesensitizedUtil(pr#282@Gitee) ### Bug修复 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index 5f5b5bd3f..780a06d1f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -5,7 +5,13 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.func.Func1; -import cn.hutool.core.util.*; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.CharUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.DesensitizedUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; import java.nio.ByteBuffer; import java.nio.charset.Charset; @@ -2976,9 +2982,9 @@ public class CharSequenceUtil { * StrUtil.padPre("1039", -1, "0");//"103" * * - * @param str 字符串 - * @param length 长度 - * @param padStr 补充的字符 + * @param str 字符串 + * @param length 长度 + * @param padStr 补充的字符 * @return 补充后的字符串 */ public static String padPre(CharSequence str, int length, CharSequence padStr) { @@ -3006,9 +3012,9 @@ public class CharSequenceUtil { * StrUtil.padPre("123", 2, '0');//"12" * * - * @param str 字符串 - * @param length 长度 - * @param padChar 补充的字符 + * @param str 字符串 + * @param length 长度 + * @param padChar 补充的字符 * @return 补充后的字符串 */ public static String padPre(CharSequence str, int length, char padChar) { @@ -3036,9 +3042,9 @@ public class CharSequenceUtil { * StrUtil.padAfter("123", -1, '0')//"" 空串 * * - * @param str 字符串,如果为{@code null},直接返回null - * @param length 长度 - * @param padChar 补充的字符 + * @param str 字符串,如果为{@code null},直接返回null + * @param length 长度 + * @param padChar 补充的字符 * @return 补充后的字符串 */ public static String padAfter(CharSequence str, int length, char padChar) { @@ -3065,9 +3071,9 @@ public class CharSequenceUtil { * StrUtil.padAfter("123", 2, "ABC");//"23" * * - * @param str 字符串,如果为{@code null},直接返回null - * @param length 长度 - * @param padStr 补充的字符 + * @param str 字符串,如果为{@code null},直接返回null + * @param length 长度 + * @param padStr 补充的字符 * @return 补充后的字符串 * @since 4.3.2 */ @@ -3629,61 +3635,6 @@ public class CharSequenceUtil { return replace(str, startInclude, endExclude, '*'); } - /** - * 脱敏,使用默认的脱敏策略 - *
- * StrUtil.hide("100", DesensitizedUtils.DesensitizedType.USER_ID)) = "0"
- * StrUtil.hide("段正淳", DesensitizedUtils.DesensitizedType.CHINESE_NAME)) = "段**"
- * StrUtil.hide("51343620000320711X", DesensitizedUtils.DesensitizedType.ID_CARD)) = "5***************1X"
- * StrUtil.hide("09157518479", DesensitizedUtils.DesensitizedType.FIXED_PHONE)) = "0915*****79"
- * StrUtil.hide("18049531999", DesensitizedUtils.DesensitizedType.MOBILE_PHONE)) = "180****1999"
- * StrUtil.hide("北京市海淀区马连洼街道289号", DesensitizedUtils.DesensitizedType.ADDRESS)) = "北京市海淀区马********"
- * StrUtil.hide("duandazhi-jack@gmail.com.cn", DesensitizedUtils.DesensitizedType.EMAIL)) = "d*************@gmail.com.cn"
- * StrUtil.hide("1234567890", DesensitizedUtils.DesensitizedType.PASSWORD)) = "**********"
- *
- *
- * @author dazer and neusoft and qiaomu
- * @see DesensitizedUtils 如果需要自定义,脱敏规则,请使用该工具类;
- * @param str 字符串
- * @param desensitizedType 脱敏类型;可以脱敏:用户id、中文名、身份证号、座机号、手机号、地址、电子邮件、密码
- * @return 脱敏之后的字符串
- * @since 5.6.2
- */
- public static String hide(CharSequence str, DesensitizedUtils.DesensitizedType desensitizedType) {
- if (isBlank(str)) {
- return EMPTY;
- }
- String newStr = String.valueOf(str);
- switch (desensitizedType) {
- case USER_ID:
- newStr = String.valueOf(DesensitizedUtils.userId());
- break;
- case CHINESE_NAME:
- newStr = DesensitizedUtils.chineseName(String.valueOf(str));
- break;
- case ID_CARD:
- newStr = DesensitizedUtils.idCardNum(String.valueOf(str),1,2);
- break;
- case FIXED_PHONE:
- newStr = DesensitizedUtils.fixedPhone(String.valueOf(str));
- break;
- case MOBILE_PHONE:
- newStr = DesensitizedUtils.mobilePhone(String.valueOf(str));
- break;
- case ADDRESS:
- newStr = DesensitizedUtils.address(String.valueOf(str), 8);
- break;
- case EMAIL:
- newStr = DesensitizedUtils.email(String.valueOf(str));
- break;
- case PASSWORD:
- newStr = DesensitizedUtils.password(String.valueOf(str));
- break;
- default:
- }
- return newStr;
- }
-
/**
* 脱敏,使用默认的脱敏策略
*
@@ -3698,15 +3649,15 @@ public class CharSequenceUtil {
* StrUtil.desensitized("1234567890", DesensitizedUtils.DesensitizedType.PASSWORD)) = "**********"
*
*
- * @author dazer and neusoft and qiaomu
- * @see DesensitizedUtils 如果需要自定义,脱敏规则,请使用该工具类;
- * @param str 字符串
+ * @param str 字符串
* @param desensitizedType 脱敏类型;可以脱敏:用户id、中文名、身份证号、座机号、手机号、地址、电子邮件、密码
* @return 脱敏之后的字符串
+ * @author dazer and neusoft and qiaomu
+ * @see DesensitizedUtil 如果需要自定义,脱敏规则,请使用该工具类;
* @since 5.6.2
*/
- public static String desensitized(CharSequence str, DesensitizedUtils.DesensitizedType desensitizedType) {
- return hide(str, desensitizedType);
+ public static String desensitized(CharSequence str, DesensitizedUtil.DesensitizedType desensitizedType) {
+ return DesensitizedUtil.desensitized(str, desensitizedType);
}
/**
@@ -4357,358 +4308,4 @@ public class CharSequenceUtil {
return strBuilder.toString();
}
- // Left/Right/Mid 用来兼容 org.apache.commons.lang3.StringUtils 使用习惯 start
- //-------------------------------------------------------------------------
- /**
- * 获取字符串的最左{@code len}个字符。
- * - *如果{@code len}个字符不可用,或者字符串为{@code null}, - * 则将无例外地返回该字符串。 - * 如果len为负,则返回一个空字符串。 - *
- * - *
- * StrUtil.left(null, *) = null
- * StrUtil.left(*, -ve) = ""
- * StrUtil.left("", *) = ""
- * StrUtil.left("neu", 0) = ""
- * StrUtil.left("neu", 2) = "ne"
- * StrUtil.left("neu", 4) = "neu"
- *
- *
- * @param str 从中获取最左边字符的字符串,可以为null
- * @param len 要求的字符串长度
- * @return 返回最左边的字符串
- * @since 5.6.2
- */
- public static String left(final String str, final int len) {
- if (str == null) {
- return null;
- }
- if (len < 0) {
- return EMPTY;
- }
- if (str.length() <= len) {
- return str;
- }
- return str.substring(0, len);
- }
-
- /**
- * 用空格在左侧填充字符串 (' ').
- * - *填充字符串到指定的长度 {@code size}.
- * - *
- * StrUtil.leftPad(null, *) = null
- * StrUtil.leftPad("", 3) = " "
- * StrUtil.leftPad("bat", 1) = "bat"
- * StrUtil.leftPad("bat", -1) = "bat"
- * StrUtil.leftPad("bat", 3) = "bat"
- * StrUtil.leftPad("bat", 5) = " bat"
- *
- *
- *
- * @param str 要填充的字符串,可以为null
- * @param size 填充到size长度
- * @return 如果不需要填充,请使用左填充字符串或原始字符串,
- * {@code null} if null String input
- * @since 5.6.2
- */
- public static String leftPad(final String str, final int size) {
- return leftPad(str, size, ' ');
- }
-
- /**
- * Left pad a String with a specified character.
- *左侧用指定的字符串进行填充.
- * - *Pad to a size of {@code size}.
- *填充到指定的长度 {@code size}.
- * - *
- * StrUtil.leftPad(null, *, *) = null
- * StrUtil.leftPad("", 3, 'z') = "zzz"
- * StrUtil.leftPad("bat", -1, 'z') = "bat"
- * StrUtil.leftPad("bat", 1, 'z') = "bat"
- * StrUtil.leftPad("bat", 3, 'z') = "bat"
- * StrUtil.leftPad("bat", 5, 'z') = "zzbat"
- *
- *
- *
- * @param str the String to pad out, may be null; 要填充的字符串,可以为null
- * @param size the size to pad to; 填充到size长度
- * @param padChar the character to pad with; 用来填充的字符
- * @return left padded String or original String if no padding is necessary,
- * 左侧填充字符串 or 如果不需要填充则返回原始字符串;
- * {@code null} if null String input; 如果输入字符串是null
- * @since 5.6.2
- */
- public static String leftPad(final String str, final int size, final char padChar) {
- if (str == null) {
- return null;
- }
- final int pads = size - str.length();
- if (pads <= 0) {
- return str; // 尽可能返回原始字符串 returns original String when possible
- }
- if (pads > PAD_LIMIT) {
- return leftPad(str, size, String.valueOf(padChar));
- }
- return repeat(padChar, pads).concat(str);
- }
-
- /**
- * 用指定的字符串左填充字符串.
- * - *填充到指定的长度 {@code size}.
- * - *
- * StrUtil.leftPad(null, *, *) = null
- * StrUtil.leftPad("", 3, "z") = "zzz"
- * StrUtil.leftPad("bat", 3, "yz") = "bat"
- * StrUtil.leftPad("bat", 5, "yz") = "yzbat"
- * StrUtil.leftPad("bat", 8, "yz") = "yzyzybat"
- * StrUtil.leftPad("bat", 1, "yz") = "bat"
- * StrUtil.leftPad("bat", -1, "yz") = "bat"
- * StrUtil.leftPad("bat", 5, null) = " bat"
- * StrUtil.leftPad("bat", 5, "") = " bat"
- *
- *
- * @param str 要填充的字符串,可以为null
- * @param size 填充到指定的长度
- * @param padStr 要填充的字符串,如果为null或空,则将其视为单个空格
- * @return 如果不需要填充,请使用左填充字符串或原始字符串,
- * {@code null} 如果为null字符串输入
- * @since 5.6.2
- */
- public static String leftPad(final String str, final int size, String padStr) {
- if (str == null) {
- return null;
- }
- if (isEmpty(padStr)) {
- padStr = SPACE;
- }
- final int padLen = padStr.length();
- final int strLen = str.length();
- final int pads = size - strLen;
- if (pads <= 0) {
- return str; // 当有可能返回原始字符串; returns original String when possible
- }
- if (padLen == 1 && pads <= PAD_LIMIT) {
- return leftPad(str, size, padStr.charAt(0));
- }
-
- if (pads == padLen) {
- return padStr.concat(str);
- } else if (pads < padLen) {
- return padStr.substring(0, pads).concat(str);
- } else {
- final char[] padding = new char[pads];
- final char[] padChars = padStr.toCharArray();
- for (int i = 0; i < pads; i++) {
- padding[i] = padChars[i % padLen];
- }
- return new String(padding).concat(str);
- }
- }
-
- /**
- * 获取字符串的最右边{@code len}个字符。
- * - *
如果{@code len}个字符不可用,或者字符串为{@code null},则将无例外地返回该字符串。如果len为负,则返回一个空字符串。
- * - *
- * StrUtil.right(null, *) = null
- * StrUtil.right(*, -ve) = ""
- * StrUtil.right("", *) = ""
- * StrUtil.right("abc", -1) = ""
- * StrUtil.right("abc", 0) = ""
- * StrUtil.right("abc", 2) = "bc"
- * StrUtil.right("abc", 4) = "abc"
- *
- *
- * @param str 从中获取最右边字符的字符串,可以为null
- * @param len 所需字符串的长度
- * @return 最右边的字符,{@code null},如果为null字符串输入
- * @since 5.6.2
- */
- public static String right(final String str, final int len) {
- if (str == null) {
- return null;
- }
- if (len < 0) {
- return EMPTY;
- }
- if (str.length() <= len) {
- return str;
- }
- return str.substring(str.length() - len);
- }
-
- /**
- * 用空格('')右填充字符串。
- *
将字符串填充为{@code size}的大小。
- * - *
- * StrUtil.rightPad(null, *) = null
- * StrUtil.rightPad("", 3) = " "
- * StrUtil.rightPad("bat", 3) = "bat"
- * StrUtil.rightPad("bat", 5) = "bat "
- * StrUtil.rightPad("bat", 1) = "bat"
- * StrUtil.rightPad("bat", -1) = "bat"
- *
- *
- * @param str 要填充的字符串,可以为null
- * @param size 填充的长度
- * @return 如果不需要填充,则使用右填充的字符串或原始字符串,
- * {@code null} 如果为null字符串输入
- * @since 5.6.2
- */
- public static String rightPad(final String str, final int size) {
- return rightPad(str, size, ' ');
- }
-
- /**
- * 用指定的字符填充到原字符串的右侧.
- * - *填充字符串到几位 {@code size}.
- * - *
- * StrUtil.rightPad(null, *, *) = null
- * StrUtil.rightPad("", 3, 'z') = "zzz"
- * StrUtil.rightPad("bat", 3, 'z') = "bat"
- * StrUtil.rightPad("bat", 5, 'z') = "batzz"
- * StrUtil.rightPad("bat", 1, 'z') = "bat"
- * StrUtil.rightPad("bat", -1, 'z') = "bat"
- *
- *
- * @param str 要填充的字符串,可以为null
- * @param size 要填充的到size位
- * @param padChar 用来填充的字符串
- * @return 返回 右侧填充字符串 or 如果不需要填充,则为原始String。
- * {@code null} 如果为null字符串输入
- * @since 5.6.2
- */
- public static String rightPad(final String str, final int size, final char padChar) {
- if (str == null) {
- return null;
- }
- final int pads = size - str.length();
- if (pads <= 0) {
- return str; // 当有可能返回原始字符串; returns original String when possible
- }
- if (pads > PAD_LIMIT) {
- return rightPad(str, size, String.valueOf(padChar));
- }
- return str.concat(repeat(padChar, pads));
- }
-
- /**
- * Right pad a String with a specified String.
- *用自定的字符串进行右侧填充.
- * - *The String is padded to the size of {@code size}.
- *填充字符串到指定长度{@code size}.
- * - *
- * StrUtil.rightPad(null, *, *) = null
- * StrUtil.rightPad("", 3, "z") = "zzz"
- * StrUtil.rightPad("bat", 3, "yz") = "bat"
- * StrUtil.rightPad("bat", 5, "yz") = "batyz"
- * StrUtil.rightPad("bat", 8, "yz") = "batyzyzy"
- * StrUtil.rightPad("bat", 1, "yz") = "bat"
- * StrUtil.rightPad("bat", -1, "yz") = "bat"
- * StrUtil.rightPad("bat", 5, null) = "bat "
- * StrUtil.rightPad("bat", 5, "") = "bat "
- *
- *
- * @param str 要填充的字符串,可以为null
- * @param size 填充到size长度
- * @param padStr 用来填充的字符串
- * @return right padded String or original String if no padding is necessary,
- * 右侧填充字符串 or 如果不需要填充则返回原始字符串
- * {@code null} if null String input
- * @since 5.6.2
- */
- public static String rightPad(final String str, final int size, String padStr) {
- if (str == null) {
- return null;
- }
- if (isEmpty(padStr)) {
- padStr = SPACE;
- }
- final int padLen = padStr.length();
- final int strLen = str.length();
- final int pads = size - strLen;
- if (pads <= 0) {
- return str; // 当有可能返回原始字符串; returns original String when possible
- }
- if (padLen == 1 && pads <= PAD_LIMIT) {
- return rightPad(str, size, padStr.charAt(0));
- }
-
- if (pads == padLen) {
- return str.concat(padStr);
- } else if (pads < padLen) {
- return str.concat(padStr.substring(0, pads));
- } else {
- final char[] padding = new char[pads];
- final char[] padChars = padStr.toCharArray();
- for (int i = 0; i < pads; i++) {
- padding[i] = padChars[i % padLen];
- }
- return str.concat(new String(padding));
- }
- }
-
- /**
- * Gets {@code len} characters from the middle of a String.
- *从字符串中间获取{@code len}个字符串.
- * - *If {@code len} characters are not available, the remainder - * of the String will be returned without an exception. If the - * String is {@code null}, {@code null} will be returned. - * An empty String is returned if len is negative or exceeds the - * length of {@code str}.
- * - *如果{@code len}个字符不可用,则将字符串的其余部分无例外地返回。 - * 如果字符串为{@code null},则将返回{@code null}。 - * 如果len为负或超过{@code str}的长度,则返回一个空字符串。
- * - *
- * StrUtil.mid(null, *, *) = null
- * StrUtil.mid(*, *, -ve) = ""
- * StrUtil.mid("", 0, *) = ""
- * StrUtil.mid("abc", 0, 2) = "ab"
- * StrUtil.mid("abc", 0, 4) = "abc"
- * StrUtil.mid("abc", 2, 4) = "c"
- * StrUtil.mid("abc", 4, 2) = ""
- * StrUtil.mid("abc", -2, 2) = "ab"
- *
- *
- *
- * @param str 给定字符串,可以为null; the String to get the characters from, may be null
- * @param pos 其实位置,如果是负数则当做0; the position to start from, negative treated as zero
- * @param len 要求字符串的长度; the length of the required String
- * @return the middle characters, {@code null} if null String input
- * @since 5.6.2
- */
- public static String mid(final String str, int pos, final int len) {
- if (str == null) {
- return null;
- }
- if (len < 0 || pos > str.length()) {
- return EMPTY;
- }
- if (pos < 0) {
- pos = 0;
- }
- if (str.length() <= pos + len) {
- return str.substring(pos);
- }
- return str.substring(pos, pos + len);
- }
- // Left/Right/Mid 用来兼容 org.apache.commons.lang3.StringUtils 使用习惯 end
- //-------------------------------------------------------------------------
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/DesensitizedUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/DesensitizedUtil.java
new file mode 100644
index 000000000..b19b7a941
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/util/DesensitizedUtil.java
@@ -0,0 +1,217 @@
+package cn.hutool.core.util;
+
+/**
+ * 脱敏工具类,支持以下类型信息的脱敏自动处理:
+ *
+ *
+ * DesensitizedUtil.desensitized("100", DesensitizedUtils.DesensitizedType.USER_ID)) = "0"
+ * DesensitizedUtil.desensitized("段正淳", DesensitizedUtils.DesensitizedType.CHINESE_NAME)) = "段**"
+ * DesensitizedUtil.desensitized("51343620000320711X", DesensitizedUtils.DesensitizedType.ID_CARD)) = "5***************1X"
+ * DesensitizedUtil.desensitized("09157518479", DesensitizedUtils.DesensitizedType.FIXED_PHONE)) = "0915*****79"
+ * DesensitizedUtil.desensitized("18049531999", DesensitizedUtils.DesensitizedType.MOBILE_PHONE)) = "180****1999"
+ * DesensitizedUtil.desensitized("北京市海淀区马连洼街道289号", DesensitizedUtils.DesensitizedType.ADDRESS)) = "北京市海淀区马********"
+ * DesensitizedUtil.desensitized("duandazhi-jack@gmail.com.cn", DesensitizedUtils.DesensitizedType.EMAIL)) = "d*************@gmail.com.cn"
+ * DesensitizedUtil.desensitized("1234567890", DesensitizedUtils.DesensitizedType.PASSWORD)) = "**********"
+ *
+ *
+ * @author dazer and neusoft and qiaomu
+ * @param str 字符串
+ * @param desensitizedType 脱敏类型;可以脱敏:用户id、中文名、身份证号、座机号、手机号、地址、电子邮件、密码
+ * @return 脱敏之后的字符串
+ * @since 5.6.2
+ */
+ public static String desensitized(CharSequence str, DesensitizedUtil.DesensitizedType desensitizedType) {
+ if (StrUtil.isBlank(str)) {
+ return StrUtil.EMPTY;
+ }
+ String newStr = String.valueOf(str);
+ switch (desensitizedType) {
+ case USER_ID:
+ newStr = String.valueOf(DesensitizedUtil.userId());
+ break;
+ case CHINESE_NAME:
+ newStr = DesensitizedUtil.chineseName(String.valueOf(str));
+ break;
+ case ID_CARD:
+ newStr = DesensitizedUtil.idCardNum(String.valueOf(str),1,2);
+ break;
+ case FIXED_PHONE:
+ newStr = DesensitizedUtil.fixedPhone(String.valueOf(str));
+ break;
+ case MOBILE_PHONE:
+ newStr = DesensitizedUtil.mobilePhone(String.valueOf(str));
+ break;
+ case ADDRESS:
+ newStr = DesensitizedUtil.address(String.valueOf(str), 8);
+ break;
+ case EMAIL:
+ newStr = DesensitizedUtil.email(String.valueOf(str));
+ break;
+ case PASSWORD:
+ newStr = DesensitizedUtil.password(String.valueOf(str));
+ break;
+ default:
+ }
+ return newStr;
+ }
+
+ /**
+ * 【用户id】不对外提供userId
+ *
+ * @return 脱敏后的主键
+ */
+ public static Long userId() {
+ return 0L;
+ }
+
+ /**
+ * 【中文姓名】只显示第一个汉字,其他隐藏为2个星号,比如:李**
+ *
+ * @param fullName 姓名
+ * @return 脱敏后的姓名
+ */
+ public static String chineseName(String fullName) {
+ if (StrUtil.isBlank(fullName)) {
+ return StrUtil.EMPTY;
+ }
+ final String name = StrUtil.subPre(fullName, 1);
+ return StrUtil.padAfter(name, StrUtil.length(fullName), "*");
+ }
+
+ /**
+ * 【身份证号】前1位 和后2位
+ *
+ * @param idCardNum 身份证
+ * @param front 保留:前面的front位数;从1开始
+ * @param end 保留:后面的end位数;从1开始
+ * @return 脱敏后的身份证
+ */
+ public static String idCardNum(String idCardNum, int front, 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);
+ }
+
+ /**
+ * 【固定电话 前四位,后两位
+ *
+ * @param num 固定电话
+ * @return 脱敏后的固定电话;
+ */
+ public static String fixedPhone(String num) {
+ if (StrUtil.isBlank(num)) {
+ return StrUtil.EMPTY;
+ }
+ return StrUtil.hide(num, 4, num.length()-2);
+ }
+
+ /**
+ * 【手机号码】前三位,后4位,其他隐藏,比如135****2210
+ *
+ * @param num 移动电话;
+ * @return 脱敏后的移动电话;
+ */
+ public static String mobilePhone(String num) {
+ if (StrUtil.isBlank(num)) {
+ return StrUtil.EMPTY;
+ }
+ return StrUtil.hide(num, 3, num.length()-4);
+ }
+
+ /**
+ * 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****
+ *
+ * @param address 家庭住址
+ * @param sensitiveSize 敏感信息长度
+ * @return 脱敏后的家庭地址
+ */
+ public static String address(String address, int sensitiveSize) {
+ if (StrUtil.isBlank(address)) {
+ return StrUtil.EMPTY;
+ }
+ int length = address.length();
+ return StrUtil.hide(address, length-sensitiveSize, length);
+ }
+
+ /**
+ * 【电子邮箱】邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.com>
+ *
+ * @param email 邮箱
+ * @return 脱敏后的邮箱
+ */
+ public static String email(String email) {
+ if (StrUtil.isBlank(email)) {
+ return StrUtil.EMPTY;
+ }
+ int index = StrUtil.indexOf(email, '@');
+ if (index <= 1) {
+ return email;
+ }
+ return StrUtil.hide(email, 1, index);
+ }
+
+ /**
+ * 【密码】密码的全部字符都用*代替,比如:******
+ *
+ * @param password 密码
+ * @return 脱敏后的邮箱
+ */
+ public static String password(String password) {
+ if (StrUtil.isBlank(password)) {
+ return StrUtil.EMPTY;
+ }
+ return StrUtil.repeat('*', password.length());
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/DesensitizedUtils.java b/hutool-core/src/main/java/cn/hutool/core/util/DesensitizedUtils.java
deleted file mode 100644
index a6f64cf31..000000000
--- a/hutool-core/src/main/java/cn/hutool/core/util/DesensitizedUtils.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package cn.hutool.core.util;
-
-/**
- * 脱敏utils
- * @author dazer and neusoft and qiaomu
- * @date 2021/3/20 09:55
- * @since 5.6.2
- */
-public class DesensitizedUtils {
- public enum DesensitizedType {
- //用户id
- USER_ID,
- //中文名
- CHINESE_NAME,
- //身份证号
- ID_CARD,
- //座机号
- FIXED_PHONE,
- //手机号
- MOBILE_PHONE,
- //地址
- ADDRESS,
- //电子邮件
- EMAIL,
- //密码
- PASSWORD;
- }
-
- /**
- * 【用户id】不对外提供userId
- * @return 脱敏后的主键
- */
- public static Long userId(){
- return 0L;
- }
-
- /**
- * 【中文姓名】只显示第一个汉字,其他隐藏为2个星号,比如:李**
- *
- * @param fullName 姓名
- * @return 脱敏后的姓名
- */
- public static String chineseName(String fullName) {
- if (StrUtil.isBlank(fullName)) {
- return "";
- }
- String name = StrUtil.left(fullName, 1);
- return StrUtil.rightPad(name, StrUtil.length(fullName), "*");
- }
-
- /**
- * 【身份证号】前1位 和后2位
- *
- * @param idCardNum 身份证
- * @param front 保留:前面的front位;从:1开始;
- * @param end 保留:后面的end位;从1:开始;
- * @return 脱敏后的身份证
- */
- public static String idCardNum(String idCardNum, int front, int end) {
- //身份证不能为空
- if (StrUtil.isEmpty(idCardNum)) {
- return "";
- }
- //需要截取的长度不能大于身份证号长度
- if ((front + end) > idCardNum.length()) {
- return "";
- }
- //需要截取的不能小于0
- if (front < 0 || end < 0) {
- return "";
- }
- //计算*的数量
- int asteriskCount = idCardNum.length() - (front + end);
- StringBuffer asteriskStr = new StringBuffer();
- for (int i = 0; i < asteriskCount; i++) {
- asteriskStr.append("*");
- }
- String regex = "(\\w{" + String.valueOf(front) + "})(\\w+)(\\w{" + String.valueOf(end) + "})";
- return idCardNum.replaceAll(regex, "$1" + asteriskStr + "$3");
- }
-
- /**
- * 【固定电话 前四位,后两位
- *
- * @param num 固定电话
- * @return 脱敏后的固定电话;
- */
- public static String fixedPhone(String num) {
- if (StrUtil.isBlank(num)) {
- return "";
- }
- return StrUtil.left(num, 4).concat(StrUtil.removePrefix(StrUtil.leftPad(StrUtil.right(num, 2), StrUtil.length(num), "*"), "****"));
- }
-
- /**
- * 【手机号码】前三位,后4位,其他隐藏,比如135****2210
- *
- * @param num 移动电话;
- * @return 脱敏后的移动电话;
- */
- public static String mobilePhone(String num) {
- if (StrUtil.isBlank(num)) {
- return "";
- }
- return StrUtil.left(num, 3).concat(StrUtil.removePrefix(StrUtil.leftPad(StrUtil.right(num, 4), StrUtil.length(num), "*"), "***"));
- }
-
- /**
- * 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****
- *
- * @param address 家庭住址
- * @param sensitiveSize 敏感信息长度
- * @return 脱敏后的家庭地址
- */
- public static String address(String address, int sensitiveSize) {
- if (StrUtil.isBlank(address)) {
- return "";
- }
- int length = StrUtil.length(address);
- return StrUtil.rightPad(StrUtil.left(address, length - sensitiveSize), length, "*");
- }
-
- /**
- * 【电子邮箱 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.com>
- *
- * @param email 邮箱
- * @return 脱敏后的邮箱
- */
- public static String email(String email) {
- if (StrUtil.isBlank(email)) {
- return "";
- }
- int index = StrUtil.indexOf(email, '@');
- if (index <= 1) {
- return email;
- } else {
- return StrUtil.rightPad(StrUtil.left(email, 1), index, "*").concat(StrUtil.mid(email, index, StrUtil.length(email)));
- }
- }
-
- /**
- * 【密码】密码的全部字符都用*代替,比如:******
- *
- * @param password 密码
- * @return 脱敏后的邮箱
- */
- public static String password(String password) {
- if (StrUtil.isBlank(password)) {
- return "";
- }
- String pwd = StrUtil.left(password, 0);
- return StrUtil.rightPad(pwd, StrUtil.length(password), "*");
- }
-}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/DesensitizedUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/DesensitizedUtilTest.java
new file mode 100644
index 000000000..ea2754336
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/util/DesensitizedUtilTest.java
@@ -0,0 +1,79 @@
+package cn.hutool.core.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * 脱敏工具类 DesensitizedUtils 安全测试
+ *
+ * @author dazer and nuesoft
+ * @see DesensitizedUtil
+ */
+public class DesensitizedUtilTest {
+
+ @Test
+ public void desensitizedTest() {
+ Assert.assertEquals("0", DesensitizedUtil.desensitized("100", DesensitizedUtil.DesensitizedType.USER_ID));
+ Assert.assertEquals("段**", DesensitizedUtil.desensitized("段正淳", DesensitizedUtil.DesensitizedType.CHINESE_NAME));
+ Assert.assertEquals("5***************1X", DesensitizedUtil.desensitized("51343620000320711X", DesensitizedUtil.DesensitizedType.ID_CARD));
+ Assert.assertEquals("0915*****79", DesensitizedUtil.desensitized("09157518479", DesensitizedUtil.DesensitizedType.FIXED_PHONE));
+ Assert.assertEquals("180****1999", DesensitizedUtil.desensitized("18049531999", DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
+ Assert.assertEquals("北京市海淀区马********", DesensitizedUtil.desensitized("北京市海淀区马连洼街道289号", DesensitizedUtil.DesensitizedType.ADDRESS));
+ Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.desensitized("duandazhi-jack@gmail.com.cn", DesensitizedUtil.DesensitizedType.EMAIL));
+ Assert.assertEquals("**********", DesensitizedUtil.desensitized("1234567890", DesensitizedUtil.DesensitizedType.PASSWORD));
+
+ Assert.assertEquals("0", DesensitizedUtil.desensitized("100", DesensitizedUtil.DesensitizedType.USER_ID));
+ Assert.assertEquals("段**", DesensitizedUtil.desensitized("段正淳", DesensitizedUtil.DesensitizedType.CHINESE_NAME));
+ Assert.assertEquals("5***************1X", DesensitizedUtil.desensitized("51343620000320711X", DesensitizedUtil.DesensitizedType.ID_CARD));
+ Assert.assertEquals("0915*****79", DesensitizedUtil.desensitized("09157518479", DesensitizedUtil.DesensitizedType.FIXED_PHONE));
+ Assert.assertEquals("180****1999", DesensitizedUtil.desensitized("18049531999", DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
+ Assert.assertEquals("北京市海淀区马********", DesensitizedUtil.desensitized("北京市海淀区马连洼街道289号", DesensitizedUtil.DesensitizedType.ADDRESS));
+ Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.desensitized("duandazhi-jack@gmail.com.cn", DesensitizedUtil.DesensitizedType.EMAIL));
+ Assert.assertEquals("**********", DesensitizedUtil.desensitized("1234567890", DesensitizedUtil.DesensitizedType.PASSWORD));
+ }
+
+ @Test
+ public void userIdTest() {
+ Assert.assertEquals(Long.valueOf(0L), DesensitizedUtil.userId());
+ }
+
+ @Test
+ public void chineseNameTest() {
+ Assert.assertEquals("段**", DesensitizedUtil.chineseName("段正淳"));
+ }
+
+ @Test
+ public void idCardNumTest() {
+ Assert.assertEquals("5***************1X", DesensitizedUtil.idCardNum("51343620000320711X", 1, 2));
+ }
+
+ @Test
+ public void fixedPhoneTest() {
+ Assert.assertEquals("0915*****79", DesensitizedUtil.fixedPhone("09157518479"));
+ }
+
+ @Test
+ public void mobilePhoneTest() {
+ Assert.assertEquals("180****1999", DesensitizedUtil.mobilePhone("18049531999"));
+ }
+
+ @Test
+ public void addressTest() {
+ Assert.assertEquals("北京市海淀区马连洼街*****", DesensitizedUtil.address("北京市海淀区马连洼街道289号", 5));
+ Assert.assertEquals("***************", DesensitizedUtil.address("北京市海淀区马连洼街道289号", 50));
+ Assert.assertEquals("北京市海淀区马连洼街道289号", DesensitizedUtil.address("北京市海淀区马连洼街道289号", 0));
+ Assert.assertEquals("北京市海淀区马连洼街道289号", DesensitizedUtil.address("北京市海淀区马连洼街道289号", -1));
+ }
+
+ @Test
+ public void emailTest() {
+ Assert.assertEquals("d********@126.com", DesensitizedUtil.email("duandazhi@126.com"));
+ Assert.assertEquals("d********@gmail.com.cn", DesensitizedUtil.email("duandazhi@gmail.com.cn"));
+ Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtil.email("duandazhi-jack@gmail.com.cn"));
+ }
+
+ @Test
+ public void passwordTest() {
+ Assert.assertEquals("**********", DesensitizedUtil.password("1234567890"));
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/DesensitizedUtilsTest.java b/hutool-core/src/test/java/cn/hutool/core/util/DesensitizedUtilsTest.java
deleted file mode 100644
index cd5853dc2..000000000
--- a/hutool-core/src/test/java/cn/hutool/core/util/DesensitizedUtilsTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package cn.hutool.core.util;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * 脱敏工具类 DesensitizedUtils 安全测试
- * @author dazer and nuesoft
- * @date 2021/3/20 22:34
- * @see DesensitizedUtils
- */
-public class DesensitizedUtilsTest {
-
- @Test
- public void userIdTest() {
- Assert.assertEquals(Long.valueOf(0L), DesensitizedUtils.userId());
- }
-
- @Test
- public void chineseNameTest() {
- Assert.assertEquals("段**", DesensitizedUtils.chineseName("段正淳"));
- }
-
- @Test
- public void idCardNumTest() {
- Assert.assertEquals("5***************1X", DesensitizedUtils.idCardNum("51343620000320711X", 1, 2));
- }
-
- @Test
- public void fixedPhoneTest() {
- Assert.assertEquals("0915*****79", DesensitizedUtils.fixedPhone("09157518479"));
- }
-
- @Test
- public void mobilePhoneTest() {
- Assert.assertEquals("180****1999", DesensitizedUtils.mobilePhone("18049531999"));
- }
-
- @Test
- public void addressTest() {
- Assert.assertEquals("北京市海淀区马连洼街*****", DesensitizedUtils.address("北京市海淀区马连洼街道289号", 5));
- Assert.assertEquals("***************", DesensitizedUtils.address("北京市海淀区马连洼街道289号", 50));
- Assert.assertEquals("北京市海淀区马连洼街道289号", DesensitizedUtils.address("北京市海淀区马连洼街道289号", 0));
- Assert.assertEquals("北京市海淀区马连洼街道289号", DesensitizedUtils.address("北京市海淀区马连洼街道289号", -1));
- }
-
- @Test
- public void emailTest() {
- Assert.assertEquals("d********@126.com", DesensitizedUtils.email("duandazhi@126.com"));
- Assert.assertEquals("d********@gmail.com.cn", DesensitizedUtils.email("duandazhi@gmail.com.cn"));
- Assert.assertEquals("d*************@gmail.com.cn", DesensitizedUtils.email("duandazhi-jack@gmail.com.cn"));
- }
-
- @Test
- public void passwordTest() {
- Assert.assertEquals("**********", DesensitizedUtils.password("1234567890"));
- }
-}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java
index 7a1e18cfb..2c028b794 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java
@@ -407,7 +407,7 @@ public class StrUtilTest {
Assert.assertNull(StrUtil.padAfter(null, 10, ' '));
Assert.assertEquals("100", StrUtil.padAfter("1", 3, '0'));
Assert.assertEquals("23", StrUtil.padAfter("123", 2, '0'));
- Assert.assertEquals("23", StrUtil.padAfter("123", -1, '0'));
+ Assert.assertEquals("", StrUtil.padAfter("123", -1, '0'));
Assert.assertNull(StrUtil.padAfter(null, 10, "ABC"));
Assert.assertEquals("1AB", StrUtil.padAfter("1", 3, "ABC"));
@@ -498,81 +498,6 @@ public class StrUtilTest {
Assert.assertEquals("this is a for 1,000", ret);
}
- @Test
- public void leftTest() {
- Assert.assertNull(StrUtil.left(null, 1));
- Assert.assertEquals("", StrUtil.left("neu", -1));
- Assert.assertEquals("", StrUtil.left("", 1));
- Assert.assertEquals("", StrUtil.left("neu", 0));
- Assert.assertEquals("ne", StrUtil.left("neu", 2));
- Assert.assertEquals("neu", StrUtil.left("neu", 4));
- }
-
- @Test
- public void leftPadTest() {
- Assert.assertNull(StrUtil.leftPad(null, 1));
- Assert.assertEquals("", StrUtil.leftPad("", -1));
- Assert.assertEquals(" ", StrUtil.leftPad("", 3));
- Assert.assertEquals("bat", StrUtil.leftPad("bat", -1));
- Assert.assertEquals("bat", StrUtil.leftPad("bat", 1));
- Assert.assertEquals("bat", StrUtil.leftPad("bat", 3));
- Assert.assertEquals(" bat", StrUtil.leftPad("bat", 5));
-
- Assert.assertNull(StrUtil.leftPad(null, 1, "z"));
- Assert.assertEquals("", StrUtil.leftPad("", -1, "z"));
- Assert.assertEquals("zzz", StrUtil.leftPad("", 3, "z"));
- Assert.assertEquals("bat", StrUtil.leftPad("bat", -1, "z"));
- Assert.assertEquals("bat", StrUtil.leftPad("bat", 1, "z"));
- Assert.assertEquals("bat", StrUtil.leftPad("bat", 3, "z"));
- Assert.assertEquals("zzbat", StrUtil.leftPad("bat", 5, "z"));
- }
-
- @Test
- public void rightTest() {
- Assert.assertNull(StrUtil.right(null, 1));
- Assert.assertEquals("", StrUtil.right("neu", -1));
- Assert.assertEquals("", StrUtil.right("", 1));
- Assert.assertEquals("", StrUtil.right("neu", 0));
- Assert.assertEquals("eu", StrUtil.right("neu", 2));
- Assert.assertEquals("neu", StrUtil.right("neu", 4));
- }
-
- @Test
- public void rightPadTest() {
- Assert.assertNull(StrUtil.rightPad(null, 1));
- Assert.assertEquals(" ", StrUtil.rightPad("", 3));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", 3));
- Assert.assertEquals("bat ", StrUtil.rightPad("bat", 5));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", 1));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", -1));
-
- Assert.assertNull(StrUtil.rightPad(null, 1, 'z'));
- Assert.assertEquals("zzz", StrUtil.rightPad("", 3, 'z'));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", 3, 'z'));
- Assert.assertEquals("batzz", StrUtil.rightPad("bat", 5, 'z'));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", 1, 'z'));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", -1, 'z'));
-
- Assert.assertNull(StrUtil.rightPad(null, 1, "z"));
- Assert.assertEquals("zzz", StrUtil.rightPad("", 3, "z"));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", 3, "z"));
- Assert.assertEquals("batzz", StrUtil.rightPad("bat", 5, "z"));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", 1, "z"));
- Assert.assertEquals("bat", StrUtil.rightPad("bat", -1, "z"));
- }
-
- @Test
- public void midTest() {
- Assert.assertNull(StrUtil.mid(null, 1, 1));
- Assert.assertEquals("", StrUtil.mid("abc", 1, -1));
- Assert.assertEquals("", StrUtil.mid("", 0, 1));
- Assert.assertEquals("ab", StrUtil.mid("abc", 0, 2));
- Assert.assertEquals("abc", StrUtil.mid("abc", 0, 4));
- Assert.assertEquals("c", StrUtil.mid("abc", 2, 4));
- Assert.assertEquals("", StrUtil.mid("abc", 4, 2));
- Assert.assertEquals("ab", StrUtil.mid("abc", -2, 2));
- }
-
@Test
public void hideTest() {
Assert.assertNull(StrUtil.hide(null, 1, 1));
@@ -582,24 +507,5 @@ public class StrUtilTest {
Assert.assertEquals("jackduan@163.com", StrUtil.hide("jackduan@163.com", 3, 2));
Assert.assertEquals("jackduan@163.com", StrUtil.hide("jackduan@163.com", 16, 16));
Assert.assertEquals("jackduan@163.com", StrUtil.hide("jackduan@163.com", 16, 17));
-
-
- Assert.assertEquals("0", StrUtil.hide("100", DesensitizedUtils.DesensitizedType.USER_ID));
- Assert.assertEquals("段**", StrUtil.hide("段正淳", DesensitizedUtils.DesensitizedType.CHINESE_NAME));
- Assert.assertEquals("5***************1X", StrUtil.hide("51343620000320711X", DesensitizedUtils.DesensitizedType.ID_CARD));
- Assert.assertEquals("0915*****79", StrUtil.hide("09157518479", DesensitizedUtils.DesensitizedType.FIXED_PHONE));
- Assert.assertEquals("180****1999", StrUtil.hide("18049531999", DesensitizedUtils.DesensitizedType.MOBILE_PHONE));
- Assert.assertEquals("北京市海淀区马********", StrUtil.hide("北京市海淀区马连洼街道289号", DesensitizedUtils.DesensitizedType.ADDRESS));
- Assert.assertEquals("d*************@gmail.com.cn", StrUtil.hide("duandazhi-jack@gmail.com.cn", DesensitizedUtils.DesensitizedType.EMAIL));
- Assert.assertEquals("**********", StrUtil.hide("1234567890", DesensitizedUtils.DesensitizedType.PASSWORD));
-
- Assert.assertEquals("0", StrUtil.desensitized("100", DesensitizedUtils.DesensitizedType.USER_ID));
- Assert.assertEquals("段**", StrUtil.desensitized("段正淳", DesensitizedUtils.DesensitizedType.CHINESE_NAME));
- Assert.assertEquals("5***************1X", StrUtil.desensitized("51343620000320711X", DesensitizedUtils.DesensitizedType.ID_CARD));
- Assert.assertEquals("0915*****79", StrUtil.desensitized("09157518479", DesensitizedUtils.DesensitizedType.FIXED_PHONE));
- Assert.assertEquals("180****1999", StrUtil.desensitized("18049531999", DesensitizedUtils.DesensitizedType.MOBILE_PHONE));
- Assert.assertEquals("北京市海淀区马********", StrUtil.desensitized("北京市海淀区马连洼街道289号", DesensitizedUtils.DesensitizedType.ADDRESS));
- Assert.assertEquals("d*************@gmail.com.cn", StrUtil.desensitized("duandazhi-jack@gmail.com.cn", DesensitizedUtils.DesensitizedType.EMAIL));
- Assert.assertEquals("**********", StrUtil.desensitized("1234567890", DesensitizedUtils.DesensitizedType.PASSWORD));
}
}