22

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

4

14 回答 14

57

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

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
于 2017-01-27T10:26:24.530 回答
19

您可以使用org.apache.commons.lang.RandomStringUtils生成随机文本/密码。例如,请参考链接。

于 2013-11-02T15:06:31.610 回答
12

以防万一它对某人有用。基于 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

于 2018-11-17T08:19:28.230 回答
6
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();

    }

}
于 2019-04-27T21:33:55.340 回答
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();
于 2013-11-02T15:11:10.133 回答
2

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

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;
        }
    }
}
于 2021-01-18T12:03:33.187 回答
2

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

于 2018-01-16T09:40:50.503 回答
2

不像George Siggouroglou 的答案那样灵活但较短的版本。

生成器类

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);
于 2020-03-09T20:40:34.740 回答
1

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

于 2013-11-02T14:54:21.873 回答
1

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

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

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

于 2021-08-29T03:41:43.090 回答
0

如果是我,我会建立一个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);

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

于 2013-11-02T15:12:25.947 回答
0

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

于 2015-09-14T21:27:45.077 回答
0

我制作了一个简单的程序,ArrayList用 ASCII 数字填充 ,然后使用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;
    }
}

希望这可以帮助!:)

于 2015-09-30T09:34:56.210 回答
0
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;
}
于 2020-09-21T14:46:56.487 回答