【问题标题】:Java password generatorJava密码生成器
【发布时间】:2013-11-13 14:52:20
【问题描述】:

我正在尝试创建一个 java 程序来创建密码,无论是全小写,小写和大写,小写和大写和数字,小写和大写以及数字和标点符号,程序还必须创建其中一个密码用户选择并且必须根据用户选择的内容生成密码长度。我已经为用户生成了可供选择的密码选项,并提示他选择一个。我现在被困在如何创建上面提到的密码类型上。一个人建议我使用 ASCII 值,然后将它们转换为文本。我知道如何将它们转换为文本,但它会显示数字、字母和标点符号。有什么方法可以只为小写字母生成 ASCII 值吗?另外,我将如何根据用户提供的长度生成密码?

【问题讨论】:

标签: java passwords generator


【解决方案1】:

您可以随机选择具有维度的数字、字母和标点符号。 Ansii 数字是从 30 到 39,小写字母从 61-7A 等等。使用ansii tables

【讨论】:

    【解决方案2】:

    您可以使用org.apache.commons.lang.RandomStringUtils 生成随机文本/密码。以this链接为例。

    【讨论】:

      【解决方案3】:

      你可以这样做:

      String lower = "abc...xyz";
      String digits = "0123456789";
      String punct = "!#$&...";
      String  ...                      // further characer classes
      

      (注意...部分您必须自己填写。)

      从用户选择的选项中,您可以通过连接相应的字符类来创建一个可供选择的字符串。

      最后你运行一个循环 n 次,其中 n 是想要的字符数。 在每一轮中,您从创建的字符串中选择一个随机字符并将其添加到结果中:

      StringBuilder sb = new StringBuilder();
      int n = ....; // how many characters in password
      String set = ....; // characters to choose from
      
      for (i= 0; i < n; i++) {
          int k = ....;   // random number between 0 and set.length()-1 inklusive
          sb.append(set.charAt(k));
      }
      String result = sb.toString();
      

      【讨论】:

        【解决方案4】:

        如果是我,我会构建字符数组 (char[] ...),它们代表您将允许的各种字符集,然后在您的生成器方法中选择适当的字符数组,并从中生成密码.复杂的部分就变成了创建字符数组...

        public String generate(char[] validchars, int len) {
            char[] password = new char[len];
            Random rand = new Random(System.nanoTime());
            for (int i = 0; i < len; i++) {
                password[i] = validchars[rand.nextInt(validchars.length)];
            }
            return new String(password);
        }
        

        那么你的问题就变成了生成 char[] 数组来代表你拥有的各种规则,以及如何将这个集合传递给 generate 方法。

        这样做的一种方法是设置与您允许的规则匹配的正则表达式规则列表,然后通过规则发送每个字符......如果它们匹配规则然后添加它们...... ..

        考虑一个看起来像这样的函数:

        public static final char[] getValid(final String regex, final int lastchar) {
            char[] potential = new char[lastchar]; // 32768 is not huge....
            int size = 0;
            final Pattern pattern = Pattern.compile(regex);
            for (int c = 0; c <= lastchar; c++) {
                if (pattern.matcher(String.valueOf((char)c)).matches()) {
                    potential[size++] = (char)c;
                }
            }
            return Arrays.copyOf(potential, size);
        }
        

        然后,您可以通过以下方式获得一个字母字符数组(仅限小写):

        getValid("[a-z]", Character.MAX_VALUE);
        

        或者,所有“单词”字符的列表:

        getValid("\\w", Character.MAX_VALUE);
        

        然后就变成了选择正则表达式来匹配您的要求,并“存储”每次重复使用的有效字符数组的情况。 (不要每次生成密码时都生成字符......)

        【讨论】:

          【解决方案5】:

          您可以尝试 Unix“pwgen”的 Java 实现。 https://github.com/antiso/pwgen-gae 它包含在 Bitbucket 中使用 CLI 实现 jpwgen 库的链接以及 GAE 部署示例的链接。

          【讨论】:

            【解决方案6】:

            我制作了一个简单的程序,用 ASCII 数字填充 ArrayList,然后使用 SecureRandom 数字生成器在 for 循环中随机化它们,您可以在其中设置您的字符数想要。

            import java.security.SecureRandom;
            import java.util.ArrayList;
            import java.util.List;
            
            public class PassGen {
            
                private String str;
                private int randInt;
                private StringBuilder sb;
                private List<Integer> l;
            
                public PassGen() {
                    this.l = new ArrayList<>();
                    this.sb = new StringBuilder();
            
                    buildPassword();
                }
            
                private void buildPassword() {
            
                    //Add ASCII numbers of characters commonly acceptable in passwords
                    for (int i = 33; i < 127; i++) {
                        l.add(i);
                    }
            
                    //Remove characters /, \, and " as they're not commonly accepted
                    l.remove(new Integer(34));
                    l.remove(new Integer(47));
                    l.remove(new Integer(92));
            
                    /*Randomise over the ASCII numbers and append respective character
                      values into a StringBuilder*/
                    for (int i = 0; i < 10; i++) {
                        randInt = l.get(new SecureRandom().nextInt(91));
                        sb.append((char) randInt);
                    }
            
                    str = sb.toString();
                }
            
                public String generatePassword() {
                    return str;
                }
            }
            

            希望这会有所帮助! :)

            【讨论】:

              【解决方案7】:

              我使用这个不可变的类。
              它使用 builder 模式
              它不支持扩展

              public final class PasswordGenerator {
              
                  private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
                  private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                  private static final String DIGITS = "0123456789";
                  private static final String PUNCTUATION = "!@#$%&*()_+-=[]|,./?><";
                  private boolean useLower;
                  private boolean useUpper;
                  private boolean useDigits;
                  private boolean usePunctuation;
              
                  private PasswordGenerator() {
                      throw new UnsupportedOperationException("Empty constructor is not supported.");
                  }
              
                  private PasswordGenerator(PasswordGeneratorBuilder builder) {
                      this.useLower = builder.useLower;
                      this.useUpper = builder.useUpper;
                      this.useDigits = builder.useDigits;
                      this.usePunctuation = builder.usePunctuation;
                  }
              
                  public static class PasswordGeneratorBuilder {
              
                      private boolean useLower;
                      private boolean useUpper;
                      private boolean useDigits;
                      private boolean usePunctuation;
              
                      public PasswordGeneratorBuilder() {
                          this.useLower = false;
                          this.useUpper = false;
                          this.useDigits = false;
                          this.usePunctuation = false;
                      }
              
                      /**
                       * Set true in case you would like to include lower characters
                       * (abc...xyz). Default false.
                       *
                       * @param useLower true in case you would like to include lower
                       * characters (abc...xyz). Default false.
                       * @return the builder for chaining.
                       */
                      public PasswordGeneratorBuilder useLower(boolean useLower) {
                          this.useLower = useLower;
                          return this;
                      }
              
                      /**
                       * Set true in case you would like to include upper characters
                       * (ABC...XYZ). Default false.
                       *
                       * @param useUpper true in case you would like to include upper
                       * characters (ABC...XYZ). Default false.
                       * @return the builder for chaining.
                       */
                      public PasswordGeneratorBuilder useUpper(boolean useUpper) {
                          this.useUpper = useUpper;
                          return this;
                      }
              
                      /**
                       * Set true in case you would like to include digit characters (123..).
                       * Default false.
                       *
                       * @param useDigits true in case you would like to include digit
                       * characters (123..). Default false.
                       * @return the builder for chaining.
                       */
                      public PasswordGeneratorBuilder useDigits(boolean useDigits) {
                          this.useDigits = useDigits;
                          return this;
                      }
              
                      /**
                       * Set true in case you would like to include punctuation characters
                       * (!@#..). Default false.
                       *
                       * @param usePunctuation true in case you would like to include
                       * punctuation characters (!@#..). Default false.
                       * @return the builder for chaining.
                       */
                      public PasswordGeneratorBuilder usePunctuation(boolean usePunctuation) {
                          this.usePunctuation = usePunctuation;
                          return this;
                      }
              
                      /**
                       * Get an object to use.
                       *
                       * @return the {@link gr.idrymavmela.business.lib.PasswordGenerator}
                       * object.
                       */
                      public PasswordGenerator build() {
                          return new PasswordGenerator(this);
                      }
                  }
              
                  /**
                   * This method will generate a password depending the use* properties you
                   * define. It will use the categories with a probability. It is not sure
                   * that all of the defined categories will be used.
                   *
                   * @param length the length of the password you would like to generate.
                   * @return a password that uses the categories you define when constructing
                   * the object with a probability.
                   */
                  public String generate(int length) {
                      // Argument Validation.
                      if (length <= 0) {
                          return "";
                      }
              
                      // Variables.
                      StringBuilder password = new StringBuilder(length);
                      Random random = new Random(System.nanoTime());
              
                      // Collect the categories to use.
                      List<String> charCategories = new ArrayList<>(4);
                      if (useLower) {
                          charCategories.add(LOWER);
                      }
                      if (useUpper) {
                          charCategories.add(UPPER);
                      }
                      if (useDigits) {
                          charCategories.add(DIGITS);
                      }
                      if (usePunctuation) {
                          charCategories.add(PUNCTUATION);
                      }
              
                      // Build the password.
                      for (int i = 0; i < length; i++) {
                          String charCategory = charCategories.get(random.nextInt(charCategories.size()));
                          int position = random.nextInt(charCategory.length());
                          password.append(charCategory.charAt(position));
                      }
                      return new String(password);
                  }
              }
              

              这是一个用法示例,

              PasswordGenerator passwordGenerator = new PasswordGenerator.PasswordGeneratorBuilder()
                      .useDigits(true)
                      .useLower(true)
                      .useUpper(true)
                      .build();
              String password = passwordGenerator.generate(8); // output ex.: lrU12fmM 75iwI90o
              

              【讨论】:

              • 这个真的很有用
              • 真的很快。
              • 保证生成与“builder”设置完全匹配的密码。例如:即使您设置了.useUpper(true),密码也不能包含任何大写字符。
              【解决方案8】:

              Apache commons text 为随机字符串生成提供了很好的替代方案。 Builder用于构造生成器,生成器之后就可以方便的生成所需的密码了。

               // Generates a 20 code point string, using only the letters a-z
               RandomStringGenerator generator = new RandomStringGenerator.Builder()
                   .withinRange('a', 'z').build();
               String randomLetters = generator.generate(20);
              

              请看

              https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/RandomStringGenerator.html

              【讨论】:

                【解决方案9】:

                以防万一它对某人有用。基于 ASCII 范围的标准 Java 8 类的单行随机密码生成器:

                String password = new Random().ints(10, 33, 122).collect(StringBuilder::new,
                        StringBuilder::appendCodePoint, StringBuilder::append)
                        .toString();
                

                String password = new Random().ints(10, 33, 122).mapToObj(i -> String.valueOf((char)i)).collect(Collectors.joining());
                

                这里密码长度为10。当然你也可以在一定范围内随机设置。 并且字符来自ASCII范围33-122,都是特殊符号,数字大小写。

                如果您只需要小写字母,您可以设置范围:97-122

                【讨论】:

                • ints() 的最后一个参数是独占的,所以它不包括代码点 122 (z),所以应该是 123。如果你使用特殊字符,你最好达到 127 个,其中包括 {|}~.
                • 我会将new Random() 更改为new SecureRandom().ints(10, 33, 122) 有点直观.ints(10, '!', '{')
                【解决方案10】:
                import java.security.SecureRandom;
                import java.util.Random;
                
                public class PasswordHelper {        
                
                    public static String generatePassword (int length) {
                
                    //minimum length of 6
                    if (length < 4) {
                        length = 6;
                    }
                
                    final char[] lowercase = "abcdefghijklmnopqrstuvwxyz".toCharArray();
                    final char[] uppercase = "ABCDEFGJKLMNPRSTUVWXYZ".toCharArray();
                    final char[] numbers = "0123456789".toCharArray();
                    final char[] symbols = "^$?!@#%&".toCharArray();
                    final char[] allAllowed = "abcdefghijklmnopqrstuvwxyzABCDEFGJKLMNPRSTUVWXYZ0123456789^$?!@#%&".toCharArray();
                
                    //Use cryptographically secure random number generator
                    Random random = new SecureRandom();
                
                    StringBuilder password = new StringBuilder(); 
                
                    for (int i = 0; i < length-4; i++) {
                        password.append(allAllowed[random.nextInt(allAllowed.length)]);
                    }
                
                    //Ensure password policy is met by inserting required random chars in random positions
                    password.insert(random.nextInt(password.length()), lowercase[random.nextInt(lowercase.length)]);
                    password.insert(random.nextInt(password.length()), uppercase[random.nextInt(uppercase.length)]);
                    password.insert(random.nextInt(password.length()), numbers[random.nextInt(numbers.length)]);
                    password.insert(random.nextInt(password.length()), symbols[random.nextInt(symbols.length)]);
                    }
                
                    return password.toString();
                
                    }
                
                }
                

                【讨论】:

                • 这应该是公认的答案;它是唯一保证密码包含所需的大/小/数字/符号组合的方法。
                【解决方案11】:

                没有George Siggouroglou's answer 的灵活但更短的版本。

                生成器类

                public final class DefaultPasswordGenerator {
                    private static final String[] charCategories = new String[] {
                            "abcdefghijklmnopqrstuvwxyz",
                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                            "0123456789"
                    };
                
                    public static String generate(int length) {
                        StringBuilder password = new StringBuilder(length);
                        Random random = new Random(System.nanoTime());
                
                        for (int i = 0; i < length; i++) {
                            String charCategory = charCategories[random.nextInt(charCategories.length)];
                            int position = random.nextInt(charCategory.length());
                            password.append(charCategory.charAt(position));
                        }
                
                        return new String(password);
                    }
                }
                

                用法

                String passWord = PasswordGenerator.generate(10);
                

                【讨论】:

                  【解决方案12】:
                  public static String getRandomPassword(int count) {
                      StringBuilder password = new StringBuilder();
                      for (int i = 0; i < count; i++) {
                          switch (getRandomInteger(0, 4)) {
                              case 0:
                                  password.append((char) getRandomInteger(65, 90));
                                  break;
                              case 1:
                                  password.append((char) getRandomInteger(97, 122));
                                  break;
                              default:
                                  password.append(getRandomInteger(0, 9));
                                  break;
                          }
                      }
                      return password.toString();
                  }
                  
                  public static int getRandomInteger(int minimum, int maximum) {
                      return ((int) (Math.random() * (maximum - minimum))) + minimum;
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    还有另一个随机字符串生成器

                    George Siggouroglou 创造了一个非常好的答案。我已经开发和更改了他的代码,更加灵活。

                    特点

                    1. 使用SecureRandom 而不是Random。你可以用Random 来代替它。
                    2. 添加了最少字符数。首先,该算法通过最少字符随机选择字符。选择最少所需字符后,将在所有可用字符中以剩余字符完成。然后随机交换所有选定的字符。
                    3. 您可以通过custom 方法使用自定义词汇。

                    示例用法

                    public class Main {
                        public static void main(String[] args) {
                            String password = new PasswordGenerator.Builder()
                                    .digits(4)
                                    .lower(1)
                                    .upper(2)
                                    .punctuation()
                                    .generate(10);
                    
                            System.out.println(password);
                    
                            // with custom
                            password = new PasswordGenerator.Builder()
                                    .custom("1579", 1)
                                    .custom("Stackoverflow", 3)
                                    .lower()
                                    .generate(6);
                            System.out.println(password);
                    
                        }
                    }
                    

                    源代码

                    import java.security.SecureRandom;
                    import java.util.ArrayList;
                    import java.util.Collections;
                    import java.util.List;
                    import java.util.Random;
                    import java.util.stream.Collectors;
                    import java.util.stream.IntStream;
                    
                    public class PasswordGenerator {
                        private final List<Rule> rules;
                    
                        private PasswordGenerator() {
                            throw new UnsupportedOperationException("Empty constructor is not supported.");
                        }
                    
                        private PasswordGenerator(Builder builder) {
                            this.rules = builder.rules;
                        }
                    
                        public String generate(int length) {
                            if (length <= 0) {
                                return "";
                            }
                    
                            // shuffle rules
                            List<Rule> shuffledRules = new ArrayList<>(rules);
                            Collections.shuffle(shuffledRules);
                    
                            // random instance, you can use `Random random = new Random();`
                            Random random = new SecureRandom();
                    
                            // 1. STAGE - SELECT MINIMUM CHARACTERS FROM RULES THAT HAVE MINIMUM COUNT.
                            List<Character> selectedChars = new ArrayList<>(selectCharactersByMinimumCount(random, shuffledRules));
                    
                            // 2. STAGE - SELECT MISSING LENGTH FROM ALL AVAILABLE CHARACTERS
                            int missingLength = length - selectedChars.size();
                            if (missingLength > 0) {
                                selectedChars.addAll(selectCharactersByMissingLength(random, shuffledRules, missingLength));
                            }
                    
                            // 3. STAGE - SHUFFLE SELECTED CHARS
                            Collections.shuffle(selectedChars);
                    
                            // 4. STAGE - RETURN RESULT
                            return selectedChars.stream().map(String::valueOf).collect(Collectors.joining());
                        }
                    
                        /**
                         * Select random characters from filter rules that they are defined minimum count value.
                         *
                         * @param random Random instance
                         * @param rules  Rules
                         * @return Randomly chosen characters
                         */
                        private List<Character> selectCharactersByMinimumCount(Random random, List<Rule> rules) {
                            return rules.stream()
                                    .filter(rule -> rule.minimumCount > 0)
                                    .flatMap(rule ->
                                            IntStream.range(0, rule.minimumCount)
                                                    .mapToObj(i -> rule.text.charAt(random.nextInt(rule.text.length()))))
                                    .collect(Collectors.toList());
                        }
                    
                        /**
                         * Select random characters from all filter rules up to complete required characters count.
                         *
                         * @param random Random instance
                         * @param rules  Rules
                         * @return Randomly chosen characters
                         */
                        private List<Character> selectCharactersByMissingLength(Random random, List<Rule> rules, int missingLength) {
                            List<Character> availableList = rules.stream()
                                    .flatMap(rule -> rule.text.chars().mapToObj(c -> (char) c))
                                    .collect(Collectors.toList());
                            // shuffle available list
                            Collections.shuffle(availableList);
                    
                            return IntStream.range(0, missingLength)
                                    .mapToObj(i -> availableList.get(random.nextInt(availableList.size()))).collect(Collectors.toList());
                        }
                    
                        public static class Builder {
                            private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
                            private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                            private static final String DIGITS = "0123456789";
                            private static final String PUNCTUATION = "!@#$%&*+-";
                    
                            private final List<Rule> rules = new ArrayList<>();
                    
                            public Builder digits() {
                                return custom(DIGITS, 0);
                            }
                    
                            public Builder digits(int minimumCount) {
                                return custom(DIGITS, minimumCount);
                            }
                    
                            public Builder lower() {
                                return lower(0);
                            }
                    
                            public Builder lower(int minimumCount) {
                                return custom(LOWER, minimumCount);
                            }
                    
                            public Builder upper() {
                                return upper(0);
                            }
                    
                            public Builder upper(int minimumCount) {
                                return custom(UPPER, minimumCount);
                            }
                    
                            public Builder punctuation() {
                                return punctuation(0);
                            }
                    
                            public Builder punctuation(int minimumCount) {
                                return custom(PUNCTUATION, minimumCount);
                            }
                    
                            public Builder custom(String text) {
                                return custom(text, 0);
                            }
                    
                            public Builder custom(String text, int minimumCount) {
                                rules.add(new Rule(text, minimumCount));
                                return this;
                            }
                    
                            public PasswordGenerator build() {
                                return new PasswordGenerator(this);
                            }
                    
                            public String generate(int length) {
                                return build().generate(length);
                            }
                        }
                    
                        private static class Rule {
                            private final String text;
                            private final int minimumCount;
                    
                            public Rule(String text, int minimumCount) {
                                this.text = text;
                                this.minimumCount = minimumCount;
                            }
                        }
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      您可以使用这个简单的算法来生成您想要的密码。

                      public static final String upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                          public static final String lowerChars = "abcdefghijklmnopqrstuvwxyz";
                          public static final String numbers = "1234567890";
                          public static final String specialChars = "!@#$%^&*()_+{}";
                      
                          public static String generatePassword(
                                  int passwordSize,
                                  boolean useUpper,
                                  boolean useLower,
                                  boolean useNumbers,
                                  boolean useSpecial
                          ) {
                              char[] password = new char[passwordSize];
                              String charSet = null;
                              Random random = new Random();
                      
                              if (useUpper) charSet += upperChars;
                              if (useLower) charSet += lowerChars;
                              if (useNumbers) charSet += numbers;
                              if (useSpecial) charSet += specialChars;
                      
                              for (int i = 0; i < passwordSize; i++) {
                                  password[i] = charSet.toCharArray()[random.nextInt(charSet.length() - 1)];
                              }
                              return String.valueOf(password);
                          }
                      

                      用法

                      generatePassword(22, true, true, true, true);
                      

                      这会返回一个字符串,因此无需转换即可直接使用。

                      【讨论】:

                        猜你喜欢
                        • 2018-11-18
                        • 1970-01-01
                        • 2011-09-23
                        • 2023-04-01
                        • 1970-01-01
                        • 2021-05-14
                        • 2021-07-01
                        • 2010-12-02
                        • 2016-08-18
                        相关资源
                        最近更新 更多