Как я могу создать пароль? - PullRequest
11 голосов
/ 16 ноября 2009

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

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

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

Ответы [ 10 ]

34 голосов
/ 16 ноября 2009

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
24 голосов
/ 09 декабря 2011

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

RandomStringUtils.random(6, 0, 0, true, true, null, new SecureRandom());
10 голосов
/ 16 ноября 2009

Используйте 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) ]);
}

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

5 голосов
/ 16 ноября 2009

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

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();
    }
}
3 голосов
/ 16 ноября 2009

Это тоже неплохо:

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

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

1 голос
/ 16 ноября 2009

Я бы сделал что-то вроде этого:

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

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

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

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

Пример результата: QU1GY7p+j+-PUW+_

System.out.println(new PasswordBuilder().addCharsOption("!@#$%&*()_-+=[]{}\\|:/?.,><", 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("!@#$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).build());
        System.out.println(new PasswordBuilder().addCharsOption("!@#$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).setSize(5).build());
    }
}
0 голосов
/ 25 апреля 2016

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

<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 заглавная буква

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

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

<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 снова и снова.

0 голосов
/ 21 декабря 2014

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

private static final int PASSWORD_SIZE = 16;
private static final String VALID_SPECIAL_CHARACTERS = "!@#$%&*()_-+=[]{}\\|:/?.,><"; // 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();
}

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

0 голосов
/ 16 ноября 2009

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

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