diff --git a/pom.xml b/pom.xml
index 30306b5..7537f92 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.imyeyu.utils
timi-utils
- 0.0.8
+ 0.0.9
true
diff --git a/src/main/java/com/imyeyu/utils/Regex.java b/src/main/java/com/imyeyu/utils/Regex.java
index c5dbf82..0839eaf 100644
--- a/src/main/java/com/imyeyu/utils/Regex.java
+++ b/src/main/java/com/imyeyu/utils/Regex.java
@@ -52,8 +52,8 @@ public class Regex {
/** 用户名 (4-16 位字母、数字、下划线) */
public static final String USERNAME = "^[a-zA-Z0-9_]{4,16}$";
- /** 密码 (6-18 位,包含字母和数字) */
- public static final String PASSWORD = "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z0-9]{6,18}$";
+ /** 密码 (6-18 位,包含字母和数字,允许特殊字符) */
+ public static final String PASSWORD = "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z0-9!#$%&()*+,\\-./:;<=>?@\\[\\]\\^_`{|}~]{6,32}$";
/** 中文字符 */
public static final String CHINESE_CHAR = "^[\\u4e00-\\u9fa5]+$";
diff --git a/src/main/java/com/imyeyu/utils/Text.java b/src/main/java/com/imyeyu/utils/Text.java
index 423ae4f..28d171b 100644
--- a/src/main/java/com/imyeyu/utils/Text.java
+++ b/src/main/java/com/imyeyu/utils/Text.java
@@ -19,7 +19,7 @@ public class Text {
public static String NUMBER_POOL = "0123456789";
- public static String LETTER_NUMBER_POOL = LETTER_POOL + LETTER_POOL;
+ public static String LETTER_NUMBER_POOL = LETTER_POOL + NUMBER_POOL;
public static String PASSWORD_CHAR_POOL = LETTER_NUMBER_POOL + "!#$%&()*+,-./:;<=>?@[]^_`{|}~";
@@ -165,11 +165,31 @@ public class Text {
SecureRandom r = new SecureRandom();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
- sb.append(pool.charAt(r.nextInt(pool.length() - 1)));
+ sb.append(pool.charAt(r.nextInt(pool.length())));
}
return sb.toString();
}
+ public static String randomPassword(int length) {
+ if (length < 6 || 32 < length) {
+ throw new IllegalArgumentException("Password length must be between 6 and 32");
+ }
+ SecureRandom r = new SecureRandom();
+ char[] chars = new char[length];
+ chars[0] = LETTER_POOL.charAt(r.nextInt(LETTER_POOL.length()));
+ chars[1] = NUMBER_POOL.charAt(r.nextInt(NUMBER_POOL.length()));
+ for (int i = 2; i < length; i++) {
+ chars[i] = PASSWORD_CHAR_POOL.charAt(r.nextInt(PASSWORD_CHAR_POOL.length()));
+ }
+ for (int i = chars.length - 1; 0 < i; i--) {
+ int j = r.nextInt(i + 1);
+ char temp = chars[i];
+ chars[i] = chars[j];
+ chars[j] = temp;
+ }
+ return new String(chars);
+ }
+
/**
* 较短的临时 UUID,如果使用在庞大的数据里,很可能会发生重复
*
diff --git a/src/test/java/test/TestRegex.java b/src/test/java/test/TestRegex.java
new file mode 100644
index 0000000..09e50b6
--- /dev/null
+++ b/src/test/java/test/TestRegex.java
@@ -0,0 +1,36 @@
+package test;
+
+import com.imyeyu.utils.Regex;
+import com.imyeyu.utils.Text;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * @author 夜雨
+ * @since 2026-06-11 14:00
+ */
+public class TestRegex {
+
+ @Test
+ public void testPassword() {
+ assert Regex.isMatch(Regex.PASSWORD, "abc123");
+ assert Regex.isMatch(Regex.PASSWORD, "abc123!");
+ assert Regex.isMatch(Regex.PASSWORD, "Abc123[]^_`{|}~");
+ assert Regex.isMatch(Regex.PASSWORD, "A1!#$%&*+,-./:@?");
+ for (int i = 0; i < 20; i++) {
+ assert Regex.isMatch(Regex.PASSWORD, Text.randomPassword(20));
+ }
+
+ assert Regex.isNotMatch(Regex.PASSWORD, "abcdef!");
+ assert Regex.isNotMatch(Regex.PASSWORD, "123456!");
+ assert Regex.isNotMatch(Regex.PASSWORD, "Ab1!");
+ assert Regex.isNotMatch(Regex.PASSWORD, "Abcdefghijklmnopqrstuvwxzy123456!");
+ assert Regex.isNotMatch(Regex.PASSWORD, "Abc123\\");
+ assert Regex.isNotMatch(Regex.PASSWORD, "Abc123\"");
+ assert Regex.isNotMatch(Regex.PASSWORD, "Abc123'");
+ assert Regex.isNotMatch(Regex.PASSWORD, "Abc123 ");
+ assertThrows(IllegalArgumentException.class, () -> Text.randomPassword(5));
+ assertThrows(IllegalArgumentException.class, () -> Text.randomPassword(33));
+ }
+}