我有这个问题 - 我的密码需要至少8个字符,至少有:
该功能几乎按预期工作,除非有时它不符合上面列出的密码的要求。如何修复代码以确保每次生成代码时都满足要求?
public class PasswordGenerator {
private static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWERCASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
private static final String NUMBERS = "0123456789";
private static final String SPECIAL_CHARACTERS = "!@#$%^&*_=+-/.?<>)";
private static final String PASSWORD_BASE = CAPITAL_LETTERS + LOWERCASE_LETTERS + NUMBERS + SPECIAL_CHARACTERS;
public static String generateRandomPassword() {
Random random = new Random();
int randomPasswordLength = 8 + random.nextInt(7);
System.out.println("random password length: " + randomPasswordLength);
char[] generatedPassword = new char[randomPasswordLength];
for(int i=0; i<randomPasswordLength; i++) {
generatedPassword[i] = PASSWORD_BASE.charAt(random.nextInt(PASSWORD_BASE.length()));
}
return new String(generatedPassword);
}
一种方法是始终预先生成这些特殊字符,然后随机完成密码。然后在最后将char[]
洗牌,以确保值不太可预测,并且不以相同的符号组开头:
private static final String CAPITAL_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWERCASE_LETTERS = "abcdefghijklmnopqrstuvwxyz";
private static final String NUMBERS = "0123456789";
private static final String SPECIAL_CHARACTERS = "!@#$%^&*_=+-/.?<>)";
private static final String ALL_CHARACTERS = CAPITAL_LETTERS + LOWERCASE_LETTERS + NUMBERS + SPECIAL_CHARACTERS;
private static final Random RAND = new Random();
public static char[] generateRandomPassword() {
int length = 8 + RAND.nextInt(7);
char[] value = new char[length];
value[0] = randomChar(CAPITAL_LETTERS);
value[1] = randomChar(LOWERCASE_LETTERS);
value[2] = randomChar(NUMBERS);
value[3] = randomChar(SPECIAL_CHARACTERS);
for (int i = 4; i < length; i++) {
value[i] = randomChar(ALL_CHARACTERS);
}
shuffle(value);
return value;
}
private static char randomChar(String str) {
return str.charAt(RAND.nextInt(str.length()));
}
private static void shuffle(char[] array) {
int index;
char temp;
for (int i = array.length - 1; i > 0; i--) {
index = RAND.nextInt(i + 1);
temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
改组的额外代码基于this answer。
不要将密码存储为String
,it's less safe than char[]
。
所以基本上你正在做的是将所有可能的字符添加到一个长字符串PASSWORD_BASE
中。然后你从这个字符串中随机抽取8-12个字符并将它们放在一起以使你成为密码。您的要求基本上只能通过纯粹的运气来实现。可能的密码可能是aaaaaaaa
。
在不中断密码随机性的情况下进行简单的修复可以检查这些条件,如果不满足,我们只需生成另一个,直到我们得到一个。该方法可能如下所示:
public static String generateRandomPassword() {
String generatedPassword;
do {
Random random = new Random();
int randomPasswordLength = 8 + random.nextInt(7);
System.out.println("random password length: " + randomPasswordLength);
generatedPassword = "";
for(int i=0; i<randomPasswordLength; i++) {
generatedPassword += PASSWORD_BASE.charAt(random.nextInt(PASSWORD_BASE.length()));
}
} while (hasNoCommonElements(generatedPassword, CAPITAL_LETTERS) &&
hasNoCommonElements(generatedPassword, NUMBERS) &&
hasNoCommonElements(generatedPassword, SPECIAL_CHARACTERS));
return new String(generatedPassword);
}
private static boolean hasNoCommonElements(String a, String b){
for (char c : a.toCharArray()) {
if(b.contains("" + c))
return false;
}
return true;
}
请注意,此实现可能具有任意运行时间,直到找到满足这些要求的密码。另请注意,这是迄今为止生成密码的最佳方式。但我希望这能帮助你理解你在做什么。