2015-11-04 98 views
1

我想創建一個根據用戶設置的限制創建密碼的密碼生成器。這些限制是:在java中生成帶有很多限制的隨機密碼

  1. 最小密碼長度
  2. 最大密碼長度
  3. 最小字母和數字
  4. 最低信
  5. 最小大寫字母
  6. 最小小寫字母
  7. 最小號
  8. 最大重複字符

我通過谷歌瞭望,大部分示例代碼都不符合我需要的要求。所以我湊合這樣的代碼:

private char[] GeneratePassword(int minLength, int maxLength, 
     int maxRepeatCharacter, int minLetterAndDigit, int minLetter, 
     int minLowerCaseLetter, int minUpperCaseLetter, int minDigit) { 

    final String LETTER = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz"; 
    final String DIGIT = ""; 
    final String[] randomSelector = {LETTER,UPPERCASE,LOWERCASE,DIGIT}; 

    int len = getRandomNumber(minLength, maxLength); 
    char[] passwordGenerated = new char[len]; 
    char[] characterUsed = new char[len]; 
    int selection; 
    int letterAndDigitUsed = 0; 
    int letterUsed = 0; 
    int lowerCaseLetterUsed = 0; 
    int upperCaseLetterUsed = 0; 
    int digitUsed = 0; 
    int index = 0; 

    if (minLength > maxLength) { 
     // throw new IllegalArgumentException("Min.Length > Max.Length!"); 
    } 

    if (minLetter + minDigit > minLetterAndDigit) { 
     // throw new IllegalArgumentException("Error!"); 
    } 

    while (index != len) { 
     selection = getRandomNumber(0, randomSelector.length); 
     if (selection == 0) { 
      passwordGenerated[index] = LETTER.charAt(RandomUtils.nextInt(0, 
        LETTER.length())); 
      if (checkRepeatCharacter(passwordGenerated[index], 
        characterUsed, index, maxRepeatCharacter) == false) { 
       characterUsed[index] = passwordGenerated[index]; 
       index++; 
       letterUsed++; 
       letterAndDigitUsed++; 
       break; 
      } 
     } else if (selection == 1) { 
      passwordGenerated[index] = UPPERCASE.charAt(RandomUtils 
        .nextInt(0, UPPERCASE.length())); 
      if (checkRepeatCharacter(passwordGenerated[index], 
        characterUsed, index, maxRepeatCharacter) == false) { 
       characterUsed[index] = passwordGenerated[index]; 
       index++; 
       upperCaseLetterUsed++; 
       letterAndDigitUsed++; 
       break; 
      } 
     } else if (selection == 2) { 
      passwordGenerated[index] = LOWERCASE.charAt(RandomUtils 
        .nextInt(0, LOWERCASE.length())); 
      if (checkRepeatCharacter(passwordGenerated[index], 
        characterUsed, index, maxRepeatCharacter) == false) { 
       characterUsed[index] = passwordGenerated[index]; 
       index++; 
       lowerCaseLetterUsed++; 
       letterAndDigitUsed++; 
       break; 
      } 
     } else if (selection == 3) { 
      passwordGenerated[index] = DIGIT.charAt(RandomUtils.nextInt(0, 
        DIGIT.length())); 
      if (checkRepeatCharacter(passwordGenerated[index], 
        characterUsed, index, maxRepeatCharacter) == false) { 
       characterUsed[index] = passwordGenerated[index]; 
       index++; 
       digitUsed++; 
       letterAndDigitUsed++; 
       break; 
      } 
     } 
    } 

    return passwordGenerated; 
} 

private boolean checkRepeatCharacter(char passwordGenerated, 
     char[] passwordUsed, int index, int maxRepeatCharacter) { 
    int characterRepeated = 0; 
    for (int i = 0; i < index; i++) { 
     if (String.valueOf(passwordUsed[i]).equals(
       String.valueOf(passwordGenerated))) { 
      characterRepeated++; 
      if (characterRepeated == maxRepeatCharacter) { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

private int getRandomNumber(int minLength, int maxLength) { 
    Random r = new Random(); 
    return r.nextInt(maxLength - minLength) + minLength; 
} 

我遇到的問題是如何確保滿足最低條件。與此同時,我不想讓我的密碼通過在相同類型的角色上重複生成。

  1. 例子:如果我把我的密碼最大長度爲10,我想爲5的最小號我更喜歡有1jP2k3o4m9而非57812aJ9tP

  2. 第二個示例:如果我將最大密碼長度設置爲5,並且我希望最小小寫字母是3,我寧願擁有Pj9mn而不是jkl5V

正如你所看到的,第二生成的密碼是試圖先fullfill的最低要求,則只能做隨機選擇到其他字符類型。這將使密碼更加脆弱。有沒有辦法來做這個算法。

編號:Generating a Random Password with Restrictions in Java

+0

'3' **不是**小寫字母。 –

+0

@ElliottFrisch你指的是哪一部分? –

+0

*我把我的最大密碼長度設置爲5,我希望最小寫字母是3 * –

回答

1

我修復了我的代碼。到目前爲止,我已經測試過,我完全按照要求工作。我留下此代碼以防萬一其他人在將來需要它。

private boolean checkRepeatCharacter(char randomCharacter, 
     ArrayList<Character> passwordUsed, int usedLength, 
     int maxRepeatCharacter) { 
    int characterRepeated = 0; 
    for (int i = 0; i < usedLength; i++) { 
     if (String.valueOf(passwordUsed.get(i)).equals(
       String.valueOf(randomCharacter))) { 
      characterRepeated++; 
      if (characterRepeated == maxRepeatCharacter) { 
       return false; 
      } 
     } 
    } 
    return true; 
} 

private boolean checkUsedIndex(int index, ArrayList<Integer> usedIndex) { 
    for (int i = 0; i < usedIndex.size(); i++) { 
     if (usedIndex.contains(index)) { 
      return false; 
     } 
    } 
    return true; 
} 

private int getRandomNumber(int minLength, int maxLength) { 
    Random r = new Random(); 
    return r.nextInt(maxLength - minLength) + minLength; 
} 

public String generatePassword(int minLength, int maxLength, 
     int maxRepeatCharacter, int minLetterAndDigit, int minLetter, 
     int minLowerCaseLetter, int minUpperCaseLetter, int minDigit, 
     int minSpecialCharacter, String specialCharacter) { 

    final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz"; 
    final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    final String DIGIT = ""; 
    StringBuilder ALL = new StringBuilder(); 
    ALL.append(LOWERCASE); 
    ALL.append(UPPERCASE); 
    ALL.append(DIGIT); 
    ALL.append(specialCharacter); 
    ALL.toString(); 

    char getRandom; 
    int length = 0; 
    StringBuilder passwordGenerated = new StringBuilder(); 
    ArrayList<Character> characterUsed = new ArrayList<Character>(); 
    ArrayList<Integer> indexUsed = new ArrayList<Integer>(); 

    int passwordLength = 0; 
    int lowerCaseLetterUsed = 0; 
    int upperCaseLetterUsed = 0; 
    int letterUsed = 0; 
    int digitUsed = 0; 
    int letterAndDigitUsed = 0; 
    int specialCharacterUsed = 0; 

    if (minLength > maxLength) { 
     throw new IllegalArgumentException("Min. Length > Max. Length!"); 
    } 

    if (minUpperCaseLetter + minLowerCaseLetter > minLetter) { 
     throw new RuntimeException(
       "mininimum Lower Case + Minimum Uppercase cannot exceed minLetter"); 
    } 
    if (minLetter + minDigit > minLetterAndDigit) { 
     throw new RuntimeException(
       "mininimum Letter + Minimum Digit cannot exceed minimum Letter And Digit"); 
    } 
    if (minLetter + minDigit + minSpecialCharacter > maxLength) { 
     throw new RuntimeException(
       "minimum Digit + minimum Letter + Minimum Special Character cannot excced maximum Length"); 
    } 

    while ((length < minLetter) && (length < minLetterAndDigit)) { 
     length = getRandomNumber(minLength, maxLength); 
    } 

    while (passwordLength != length) { 
     while (letterAndDigitUsed < minLetterAndDigit) { 
      while (letterUsed < minLetter) { 
       lowerCaseLetterUsed = 0; 
       for (int i = 0; lowerCaseLetterUsed < minLowerCaseLetter; i++) { 
        int index = getRandomNumber(0, length); 
        if (checkUsedIndex(index, indexUsed) == true) { 
         getRandom = LOWERCASE.charAt(getRandomNumber(0, 
           LOWERCASE.length())); 
         if (checkRepeatCharacter(getRandom, characterUsed, 
           characterUsed.size(), maxRepeatCharacter) == true) { 
          passwordGenerated.append(getRandom); 
          characterUsed.add(getRandom); 
          indexUsed.add(index); 
          lowerCaseLetterUsed++; 
          letterUsed++; 
          letterAndDigitUsed++; 
          passwordLength++; 
          if (letterUsed == minLetter) { 
           break; 
          } 
         } 
        } 
       } 
       if (letterAndDigitUsed == minLetterAndDigit) { 
        break; 
       } 
       upperCaseLetterUsed = 0; 
       for (int i = 0; upperCaseLetterUsed < minUpperCaseLetter; i++) { 
        int index = getRandomNumber(0, length); 
        if (checkUsedIndex(index, indexUsed) == true) { 
         getRandom = UPPERCASE.charAt(getRandomNumber(0, 
           UPPERCASE.length())); 
         if (checkRepeatCharacter(getRandom, characterUsed, 
           characterUsed.size(), maxRepeatCharacter) == true) { 
          passwordGenerated.append(getRandom); 
          characterUsed.add(getRandom); 
          indexUsed.add(index); 
          lowerCaseLetterUsed++; 
          letterUsed++; 
          letterAndDigitUsed++; 
          passwordLength++; 
          if (letterUsed == minLetter) { 
           break; 
          } 
         } 
        } 
       } 
       if (letterAndDigitUsed == minLetterAndDigit) { 
        break; 
       } 
      } 
      for (int i = 0; digitUsed < minDigit; i++) { 
       int index = getRandomNumber(0, length); 
       if (checkUsedIndex(index, indexUsed) == true) { 
        getRandom = DIGIT.charAt(getRandomNumber(0, 
          DIGIT.length())); 
        if (checkRepeatCharacter(getRandom, characterUsed, 
          characterUsed.size(), maxRepeatCharacter) == true) { 
         passwordGenerated.append(getRandom); 
         characterUsed.add(getRandom); 
         indexUsed.add(index); 
         digitUsed++; 
         letterAndDigitUsed++; 
         passwordLength++; 
        } 
       } 
      } 
     } 
     for (int i = 0; specialCharacterUsed < minSpecialCharacter; i++) { 
      if (checkUsedIndex(i, indexUsed) == true) { 
       getRandom = specialCharacter.charAt(getRandomNumber(0, 
         specialCharacter.length())); 
       if (checkRepeatCharacter(getRandom, characterUsed, 
         characterUsed.size(), maxRepeatCharacter) == true) { 
        passwordGenerated.append(getRandom); 
        characterUsed.add(getRandom); 
        indexUsed.add(i); 
        specialCharacterUsed++; 
        passwordLength++; 
       } 
      } 
     } 
     for (int i = 0; i < length; i++) { 
      if (checkUsedIndex(i, indexUsed) == true) { 
       getRandom = ALL.charAt(getRandomNumber(0, ALL.length())); 
       if (checkRepeatCharacter(getRandom, characterUsed, 
         characterUsed.size(), maxRepeatCharacter) == true) { 
        passwordGenerated.append(getRandom); 
        characterUsed.add(getRandom); 
        indexUsed.add(i); 
        passwordLength++; 
       } 
      } 
     } 
    } 
    return passwordGenerated.toString(); 
} 
2

我想看看像VT-密碼:

https://code.google.com/p/vt-middleware/wiki/vtpassword

除了與密碼驗證工作的基礎上有一些相當標準所要求的特性,提供靈活的機制它提供了生成符合由「字符規則」列表定義的條件的密碼的支持:

https://code.google.com/p/vt-middleware/wiki/vtpassword#Generating_passwords

值得注意的是,該項目已經從孵化畢業,現在被稱爲帕西 - http://www.passay.org/

當前password generator JavaDocs不反映與vt-password一樣可用的同一組字符規則。您可以使用vt-password運行一段時間,或者提供您自己的實現以與Passay生成器一起工作(如果還需要,也使用+驗證器)。