如何保证随机密码中的某些字符

时间:2014-09-12 19:18:26

标签: java string random alphanumeric

我正在使用此函数生成长度为11的随机密码,如this帖子所示:

import java.util.Random;

public class RandomPassword {
    public static void main(String[] args){
        RandomPassword r = new RandomPassword(11);
        System.out.print(r.nextString());

    }
      private static final char[] symbols;

      static {
        StringBuilder tmp = new StringBuilder();

        for (char ch = '0'; ch <= '9'; ++ch)
          tmp.append(ch);
        for (char ch = 'a'; ch <= 'z'; ++ch)
          tmp.append(ch);
        for (char ch = 'A'; ch <= 'Z'; ++ch)
              tmp.append(ch);


        symbols = tmp.toString().toCharArray();
      }   

      private final Random random = new Random();

      private final char[] buf;

      public RandomPassword(int length) {
        if (length < 1)
          throw new IllegalArgumentException("length < 1: " + length);
        buf = new char[length];
      }

      public String nextString() {
        for (int idx = 0; idx < buf.length; ++idx) 
          buf[idx] = symbols[random.nextInt(symbols.length)];
        return new String(buf);
      }
}

但是我需要修改它,这样我才能保证至少有一个大写字母,一个数字和一个小写字母。现在,密码可能包含所有大写/小写/数字,我们至少需要AD中的一个接受。感谢任何帮助。谢谢。

***我被告知最好像这样在nextString()中循环:

public String nextString() {
        for (int idx = 0; idx < buf.length; ++idx) 
          if(buf[buf.length%3].equals(num/lower/cap)){
            buf[idx] = symbols[random.nextInt(symbols.length)];
        }
        .
        .
        .
        return new String(buf);
      }

您怎么看?

6 个答案:

答案 0 :(得分:3)

  1. 创建一个真正的随机密码
  2. 使用正则表达式查看随机密码是否符合您的要求
  3. 如果没有,请从密码中选择一个随机字符并将其修改为随机选择 符号(或数字或大写字母)
  4. 这可以防止循环,并且还具有真正随机的好处。

    或者,如果你可以丢失一些熵,你可以:

    1. 创建四个随机字符串:小写(长度:5),大写(4),数字(1)和符号(1)
    2. 连接字符串
    3. 使用Collections.shuffle
    4. 对字符串进行随机播放

答案 1 :(得分:1)

遍历数组中的字符以确保每个字符类都包含在其中。然后,如果失败,只需生成一个新的随机字符串。这样可以确保所有内容都包含在内,并且不会经常验证。

答案 2 :(得分:1)

我建议常规表达式搜索一组预先设定的字符/数字大写/小写和错误信息

   public String getPassword(){
      SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
      byte[] salt = new byte[16];
      sr.nextBytes(salt);

      return wellformedPassword(salt.toString()) ? salt.toString() : secured(salt.toString());

   }

   public String secured(String pass){
       return string1.replaceFirst(Pattern.quote("[a-z]", "Z");
   }

   public boolean wellformedPassword(String pass){
      return checkRegExp(pass, "\\d") 
              && checkRegExp(pass, "[A-Z]")
              && checkRegExp(pass, "[a-z]");
   }

   public boolean checkRegExp(String str, String pattern){
      Pattern p = Pattern.compile(pattern);
      Matcher n = p.matcher(str);
      return n.find();
   } 

SHA确保你小写字母和数字,然后你只需要转一个(在我的情况下)或更多到上面。

这是一种可以改进的虚拟方法。分享您的代码,以便我以后无法为其他任何人编辑我的答案。

你可以得到那个字符并把它变成上面而不是Z,但我想你可以开始使用它。

答案 3 :(得分:0)

这个“作弊”(比它可能弱),但它符合通常的要求(或者可以修改以满足它们):

import java.util.Random;
public class Password {
    private static final String UPPER = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
    private static final String LOWER = "abcdefghijklmnpqrstuvwxyz";
    private static final String NUMBER = "123456789";
    private static final String SPECIAL = "!@#$%&*+?";
    private Random randGen = new Random();
    public static void main(String[] argv) {
        Password me = new Password();
        for (int i = 0; i <= 10; i++) {
            me.printPassword();
        }
    }
    private void printPassword() {
        StringBuffer buf = new StringBuffer();
        buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
        buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
        buf.append(NUMBER.charAt(Math.abs(randGen.nextInt()) % NUMBER.length()));
        for (int i = 0; i <= 4; i++) {
            buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
        }
        buf.append(UPPER.charAt(Math.abs(randGen.nextInt()) % UPPER.length()));
        buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
        System.out.println(buf.toString());
    }
}

我有另一种算法更好,但丢失了。

(我喜欢打印多个“建议”,然后选择一个最容易记住的建议。)

答案 4 :(得分:0)

我真的不知道它有多可靠但只是一次尝试

List<Character> listOfUpperCaseLetter = new ArrayList<Character>();
for(int i = 65;i<91;i++){
    char ch = (char)i;
    listOfUpperCaseLetter.add(ch);
}
List<Character> listOfLowerCaseLetter = new ArrayList<Character>();
for(int i = 97;i<123;i++){
    char ch = (char)i;
    listOfLowerCaseLetter.add(ch);
}
List<Integer> listOfInt = new ArrayList<Integer>();
for(int i =0;i<10;i++){
    listOfInt.add(i);
}
StringBuilder br = new StringBuilder();
Collections.shuffle(listOfLowerCaseLetter);
Collections.shuffle(listOfUpperCaseLetter);
Collections.shuffle(listOfInt);
br.append(listOfUpperCaseLetter.get(0));
br.append(listOfLowerCaseLetter.get(1));
br.append(listOfLowerCaseLetter.get(3));
br.append(listOfInt.get(1));
br.append(listOfInt.get(0));
br.append(listOfLowerCaseLetter.get(2));
br.append(listOfUpperCaseLetter.get(1));
br.append(listOfLowerCaseLetter.get(0));
br.append(listOfUpperCaseLetter.get(2));
br.append(listOfInt.get(2));

System.out.println(br.toString());

答案 5 :(得分:0)

我只是添加了if/else语句,说要添加symbols数组的某些成员(0-10,11-35,36-61)。这保证了所需要的。有时最简单的答案是最好的答案。谢谢你的想法。

          if (idx == 0){
            buf[idx] = symbols[random.nextInt(10)]; 
          }else if (idx == 1){
            buf[idx] = symbols[10 + random.nextInt(35-10+1)];
          }else if(idx == 2){
            buf[idx] = symbols[36 + random.nextInt(61-36+1)];
          }else{
            buf[idx] = symbols[random.nextInt(symbols.length)];
          }