我遇到了这个问题-我的密码必须至少包含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);
}
答案 0 :(得分:2)
一种方法是始终先生成这些特殊字符,然后随机完成密码。然后在末尾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[]
。
答案 1 :(得分:1)
因此,基本上,您正在做的是将所有可能的字符添加到一个长字符串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;
}
请注意,此实现可能会任意运行,直到找到满足这些要求的密码。还要注意,到目前为止,这不是生成密码的最佳方法。但我希望这可以帮助您了解自己在做什么。