繁体   English   中英

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

[英]How to guarantee certain characters in a random password

我使用该功能可以生成长度为11的随机密码,在看到这个帖子:

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

你怎么看?

  1. 创建一个真正随机的密码
  2. 使用正则表达式查看随机密码是否满足您的要求
  3. 如果不是,请从密码中选择一个随机字符并将其修改为随机选择的符号(或数字或大写字母)

这将防止循环,并且还具有真正随机的好处。

或者,如果可以接受一些熵损失,则可以:

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

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

我建议您定期搜索一组预定义的字符/数字(大写/小写)和错误消息

   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的上方,而不是Z,但是我想您可以开始使用。

此“作弊”(比可能弱),但满足通常的要求(或可以进行修改以满足这些要求):

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

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

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

我真的不知道它有多可靠,但尝试一下

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());

我只是添加了一条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)];
          }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM