生成随机密码,密码至少要包含 大写字母,小写字母,数字,特殊字符四者中的三种组合,并且不能包含中文,还要满足线程安全。
代码如下:
public class PasswordGenerator {
private static final char[] CHARR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890~!@#$%^&*.?-+=_"
.toCharArray();
private static final String PASSWORD_REGEX = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\W_!@#$%^&*`~()-+=]{8,16}$";
private static final String NO_CHINESE_REGEX = "^[^\\u4e00-\\u9fa5]+$";
private static final Pattern PASSWORD_PATTERN = Pattern.compile(PASSWORD_REGEX);
private static final Pattern NO_CHINESE_PATTERN = Pattern.compile(NO_CHINESE_REGEX);
public static String generatePassword(int length) {
length = length < 8 ? 8 : length;
length = length > 16 ? 16 : length;
String result = getRandomPassword(length);
Matcher m = PASSWORD_PATTERN.matcher(result);
Matcher m1 = NO_CHINESE_PATTERN.matcher(result);
if (m.matches() && m1.matches()) {
return result;
}
return generatePassword(length);
}
private static String getRandomPassword(int length) {
StringBuilder sb = new StringBuilder();
ThreadLocalRandom r = ThreadLocalRandom.current();
for (int x = 0; x < length; ++x) {
sb.append(CHARR[r.nextInt(CHARR.length)]);
}
return sb.toString();
}
}
为了实现线程安全,这里用到了ThreadLocalRandom,而非Random。保证了高并发场景下密码随机性。
密码的正则表达式以及js测试代码如下,可通过F12验证,当前正则指定了字符串长度为8-16位,你可以根据实际需求略做调整。
var pattern = /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\W_!@#$%^&*`~()-+=]{8,16}$/;
console.log("匹配吗:"+pattern.test("Pas33332w0rd"));
注意:
部分同学私信我说用了我的代码,但是用了自己的正则会出现栈溢出的情况,这是因为你的正则包含了一些没在CHARR中出现的特殊符号,你需要修改CHARR,如果把那些特殊符号添加进去。