Как создать пароль?

Я хочу дать миллионному паролю некоторым пользователям, которые должны быть похожими:

  • Он должен иметь не менее 6 символов
  • Он должен иметь цифры, а также буквы

Должен ли я использовать Random здесь? Как?

Ответ 1

RandomStringUtils от Apache Commons Lang предоставляют некоторые методы для создания рандомизированной строки, которая может использоваться как пароль.


Вот несколько примеров создания паролей из 8 символов:

// Passwords with only alphabetic characters.
for (int i = 0; i < 8; i++) {
    System.out.println(RandomStringUtils.randomAlphabetic(8));
}
System.out.println("--------");
// Passwords with alphabetic and numeric characters.
for (int i = 0; i < 8; i++) {
    System.out.println(RandomStringUtils.randomAlphanumeric(8));
}

который создает следующий результат:

zXHzaLdG
oDtlFDdf
bqPbXVfq
tzQUWuxU
qBHBRKQP
uBLwSvnt
gzBcTnIm
yTUgXlCc
--------
khDzEFD2
cHz1p6yJ
3loXcBau
F6NJAQr7
PyfN079I
8tJye7bu
phfwpY6y
62q27YRt

Конечно, у вас также есть методы, которые могут ограничивать набор символов, разрешенных для генерации пароля:

for (int i = 0; i < 8; i++) {
    System.out.println(RandomStringUtils.random(8, "abcDEF123"));
}

создаст только пароли с символами a, b, c, D, E, F, 1, 2 или 3:

D13DD1Eb
cac1Dac2
FE1bD2DE
2ab3Fb3D
213cFEFD
3c2FEDDF
FDbFcc1E
b2cD1c11

Ответ 2

При использовании Apache RandomStringUtils по соображениям безопасности (например, пароли) очень важно объединить использование источника SecureRandom:

RandomStringUtils.random(6, 0, 0, true, true, null, new SecureRandom());

Ответ 3

Используйте SecureRandom, он предоставляет более случайные пароли.

Вы можете создать один пароль, используя что-то вроде этого (обратите внимание: непроверенный код).

// put here all characters that are allowed in password
char[] allowedCharacters = {'a','b','c','1','2','3','4'};

SecureRandom random = new SecureRandom();
StringBuffer password = new StringBuffer();

for(int i = 0; i < PASSWORD_LENGTH; i++) {
    password.append(allowedCharacters[ random.nextInt(allowedCharacters.length) ]);
}

Обратите внимание, что это не гарантирует, что каждый пароль будет иметь как цифры, так и символы.

Ответ 4

Вот один, который я написал некоторое время назад:

package com.stackoverflow.does.my.code.for.me;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

public class PasswordUtil {

    /** Minimum password length = 6 */
    public static final int MIN_PASSWORD_LENGTH = 6;
    /** Maximum password length = 8 */
    public static final int MAX_PASSWORD_LENGTH = 8;

    /** Uppercase characters A-Z */
    public static final char[] UPPERS = new char[26];
    /** Lowercase characters a-z */
    public static final char[] LOWERS = new char[26];
    /**
     * Printable non-alphanumeric characters, excluding space.
     */
    public static final char[] SPECIALS = new char[32];
    public static final char[] DIGITS = new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    static {
        // Static initializer block for populating arrays
        int U = 'A';
        int l = 'a';
        int d = '0';
        for (int i = 0; i < 26; i++) {
            UPPERS[i] = (char) (U + i);
            LOWERS[i] = (char) (l + i);
            if (i < 10) {
                DIGITS[i] = (char) (d + i);
            }
        }
        int p = 0;
        for (int s = 33; s < 127; s++) {
            char specialChar = (char) 32;

            if (s >= 'a' && s <= 'z')
                s = 'z' + 1; // jump over 'a' to 'z'
            else if (s >= 'A' && s <= 'Z')
                s = 'Z' + 1; // jump over 'A' to 'Z'
            else if (s >= '0' && s <= '9')
                s = '9' + 1; // jump over '0' to '9'

            specialChar = (char) s;
            SPECIALS[p] = specialChar;
            p++;
        }
    }

    public String generatePassword() {
        List<char[]> activeSets = new ArrayList<char[]>(4);
        List<char[]> inactiveSets = new ArrayList<char[]>(4);

        activeSets.add(UPPERS);
        activeSets.add(LOWERS);
        activeSets.add(SPECIALS);
        activeSets.add(DIGITS);

        SecureRandom random = new SecureRandom();

        int passwordLength = 5 + random.nextInt(3);
        StringBuffer password = new StringBuffer(passwordLength + 1);

        for (int p = 0; p <= passwordLength; p++) {
            char[] randomSet = null;
            if (activeSets.size() > 1) {
                int rSet = random.nextInt(activeSets.size());
                randomSet = activeSets.get(rSet);
                inactiveSets.add(randomSet);
                activeSets.remove(rSet);
            } else {
                randomSet = activeSets.get(0);
                inactiveSets.add(randomSet);
                activeSets.clear();
                activeSets.addAll(inactiveSets);
                inactiveSets.clear();
            }
            int rChar = random.nextInt(randomSet.length);
            char randomChar = randomSet[rChar];
            password.append(randomChar);
        }

        return password.toString();
    }
}

Ответ 5

Это тоже приятный вариант:

String password = Integer.toString((int) (Math.random() * Integer.MAX_VALUE), 36);

Однако он не гарантирует, что пароль всегда содержит как цифры, так и буквы, но большинство вышеупомянутых предложений также этого не делают.

Ответ 6

Что бы я сделал, это примерно так:

  • Создайте два массива, один с разрешенными буквами и другой с разрешенными цифрами.
  • Используйте Random для определения длины пароля.
  • Используйте Random для определения того, является ли следующий символ буквой или цифрой.
  • Используйте Random еще раз для создания индекса для массива букв или цифр (в зависимости от того, что вы получили на шаге 3). Добавьте полученный пароль к паролю.
  • Повторяйте с 3 до тех пор, пока не получите количество символов, полученных в 2.

Ответ 7

Это будет самый простой:)

String char_group = "abcdefghijklmnopqrstuvwxyz";
String digit_group = "123456789";

// first choose a len of pwd
Random ran = new Random();
int pwd_len = ran.nextInt(50); //50 is the max length of password,say
// check that pwd_len is not less than 6
// do the check here

// finally create the password..
StringBuffer pwd = new StringBuffer();
Random RNG = new Random();
for (int i = 0; i < pwd_len ; i++) {
    int randomNum = RNG.nextInt(100);
    char c = '';
    // Here 25% is the ratio of mixing digits
    // in the password, you can change 4 to any
    // other value to change the depth of mix
    // or you can even make it random. 
    if (randomNum % 4 == 0) {
        c = digit_group[randomNum  % digit_group.length];
    } else {
        c = char_group[randomNum  % char_group.length];
    }
    pwd.append(c);
}
return pwd.toString();

Ответ 8

Немного поздно, но обычно я использую следующий код:

private static final int PASSWORD_SIZE = 16;
private static final String VALID_SPECIAL_CHARACTERS = "[email protected]#$%&*()_-+=[]{}\\|:/?.,><"; // Note the double \ as escape

private static String createPassword() {
    SecureRandom random = new SecureRandom();
    StringBuilder password = new StringBuilder();
    while (password.length() < PASSWORD_SIZE) {
        char character = (char) random.nextInt(Character.MAX_VALUE);
        if ((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || VALID_SPECIAL_CHARACTERS.contains(String.valueOf(character))) {
            password.append(character);
        }
    }
    return password.toString();
}

Нет гарантии, что в пароле всегда будет символ номера, специальный символ, строчный регистр и верхний регистр. Это можно было бы применить, добавив сначала символ и цифру, однако это создало бы пароли, которые немного предсказуемы.

Ответ 9

Вот как вы можете убедиться, что сгенерированный пароль соответствует вашим критериям пароля, например: в вашем случае я бы использовал это регулярное выражение:

<code>String regex = "^(?=[a-zA-Z0-9ñÑ]*\d)(?=[a-zA-Z0-9ñÑ]*[a-z])(?=[a-zA-Z0-9ñÑ]*[A-Z])[a-zA-Z0-9ñÑ]{6,}$"</code>

Это регулярное выражение соответствует следующим критериям:

1.- не менее 1 буквы нижнего регистра

2.- по крайней мере 1 буква upperCase

3.- не менее 1 цифры (число)

4. - не менее 6 символов (обратите внимание, что добавление числа больше 6 после запятой в конце регулярного выражения теперь будет соответствовать критериям, по меньшей мере, 6 символов и максимальному количеству того, что вы там вложили)

<code>char[] char = {'a','b','c','d','e','f','g','h',...};

SecureRandom random = new SecureRandom();
StringBuffer password = new StringBuffer();</code>

while(!password.toString().matches("your regex")){
    for(int i = 0; i < 8; i++) {
    password.append(char [ random.nextInt(char .length) ]);
    }
}
System.out.println(password.toString());

Что делает этот код, так это то, что while ваш сгенерированный пароль не соответствует вашим критериям, он будет цикл цикла for снова и снова.

Ответ 10

Реализовано PasswordBuilder. Поддерживает ограничение passwrod, должен иметь символы и сколько из них, диапазоны char и список из них.

Пример использования:

System.out.println(new PasswordBuilder().addCharsOption("[email protected]#$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).build());

Результат: QU1GY7p+j+-PUW+_

System.out.println(new PasswordBuilder().addCharsOption("[email protected]#$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).setSize(5).build());

Результат: %,4NX

Реализация:

//Version=1.0
//Source=https://www.dropbox.com/s/3a4uyrd2kcqdo28/PasswordBuilder.java?dl=0
//Dependencies=java:7 com.google.guava:guava:18.0 commons-lang:commons-lang:2.6

import com.google.common.primitives.Chars;
import org.apache.commons.lang.ArrayUtils;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by alik on 5/26/16.
 */
public class PasswordBuilder {
    private int size = 16;
    private List<Character> options = new ArrayList<>();
    private Map<List<Character>, Integer> musts = new java.util.LinkedHashMap<>();
    private SecureRandom secureRandom = new SecureRandom();

    public PasswordBuilder() {
    }

    public PasswordBuilder setSize(int size) {
        this.size = size;
        return this;
    }

    public PasswordBuilder addRangeOption(char from, char to, int mustCount) {
        List<Character> option = new ArrayList<>(to - from + 1);
        for (char i = from; i < to; ++i) {
            option.add(i);
        }
        return addOption(option, mustCount);
    }

    public PasswordBuilder addCharsOption(String chars, int mustCount) {
            return addOption(Chars.asList(chars.toCharArray()), mustCount);
    }

    public PasswordBuilder addOption(List<Character> option, int mustCount) {
        this.options.addAll(option);
        musts.put(option, mustCount);
        return this;

    }

    public String build() {
        validateMustsNotOverflowsSize();
        Character[] password = new Character[size];

        // Generate random from musts
        for (Map.Entry<List<Character>, Integer> entry : musts.entrySet()) {
            for (int i = 0; i < entry.getValue(); i++) {
                int charIndex = secureRandom.nextInt(entry.getKey().size());
                char c = entry.getKey().get(charIndex);
                addChar(password, c);
            }
        }

        // Generate from overall
        for (int i = 0; i < password.length; i++) {
            if (password[i] != null) continue;
            password[i] = options.get(secureRandom.nextInt(options.size()));
        }
        return new String(ArrayUtils.toPrimitive(password));
    }

    private void addChar(Character[] password, char c) {
        int i;
        for (i = secureRandom.nextInt(password.length); password[i] != null; i = secureRandom.nextInt(password.length)) {
        }
        password[i] = c;
    }

    private void validateMustsNotOverflowsSize() {
        int overallMusts = 0;
        for (Integer mustCount : musts.values()) {
            overallMusts += mustCount;
        }
        if (overallMusts > size) {
            throw new RuntimeException("Overall musts exceeds the requested size of the password.");
        }
    }

    public static void main(String[] args) {
        System.out.println(new PasswordBuilder().addCharsOption("[email protected]#$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).build());
        System.out.println(new PasswordBuilder().addCharsOption("[email protected]#$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).setSize(5).build());
    }
}