密码生成器有限制java

问题描述 投票:-1回答:2

我有这个问题 - 我的密码需要至少8个字符,至少有:

  • 1个大写字母
  • 1个小写字母
  • 1个特殊字符

该功能几乎按预期工作,除非有时它不符合上面列出的密码的要求。如何修复代码以确保每次生成代码时都满足要求?

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);
}
java arrays random
2个回答
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

不要将密码存储为Stringit's less safe than char[]


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;
}

请注意,此实现可能具有任意运行时间,直到找到满足这些要求的密码。另请注意,这是迄今为止生成密码的最佳方式。但我希望这能帮助你理解你在做什么。

© www.soinside.com 2019 - 2024. All rights reserved.