Как генерировать случайные буквенно-цифровые строки?

Я ищу простой алгоритм Java для генерации псевдослучайной Альфа-числовой строки. В моей ситуации он будет использоваться как уникальный идентификатор сеанса/ключа, который "вероятно" будет уникальным для поколения 500K+ (мои потребности на самом деле не требуют ничего более сложного). В идеале, я мог бы указать длину в зависимости от моих потребностей уникальность. Например, сгенерированная строка длины 12 может выглядеть примерно как "AEYGF7K0DM1X".

30 ответов


алгоритм

чтобы сгенерировать случайную строку, объедините символы, нарисованные случайным образом из набора допустимых символов, пока строка не достигнет желаемой длины.

реализация

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

import java.security.SecureRandom;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;

public class RandomString {

    /**
     * Generate a random string.
     */
    public String nextString() {
        for (int idx = 0; idx < buf.length; ++idx)
            buf[idx] = symbols[random.nextInt(symbols.length)];
        return new String(buf);
    }

    public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public static final String lower = upper.toLowerCase(Locale.ROOT);

    public static final String digits = "0123456789";

    public static final String alphanum = upper + lower + digits;

    private final Random random;

    private final char[] symbols;

    private final char[] buf;

    public RandomString(int length, Random random, String symbols) {
        if (length < 1) throw new IllegalArgumentException();
        if (symbols.length() < 2) throw new IllegalArgumentException();
        this.random = Objects.requireNonNull(random);
        this.symbols = symbols.toCharArray();
        this.buf = new char[length];
    }

    /**
     * Create an alphanumeric string generator.
     */
    public RandomString(int length, Random random) {
        this(length, random, alphanum);
    }

    /**
     * Create an alphanumeric strings from a secure generator.
     */
    public RandomString(int length) {
        this(length, new SecureRandom());
    }

    /**
     * Create session identifiers.
     */
    public RandomString() {
        this(21);
    }

}

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

создайте небезопасный генератор для 8-символьных идентификаторов:

RandomString gen = new RandomString(8, ThreadLocalRandom.current());

создайте безопасный генератор для идентификаторов сеанса:

RandomString session = new RandomString();

создайте генератор с кодами легк-к-чтения для печати. Строки длиннее полных буквенно-цифровых строк, чтобы компенсировать использование меньшего количества символов:

String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);

использовать в качестве идентификаторов сессии

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

существует напряжение между длиной и безопасностью. Более короткие идентификаторы легче угадать, потому что возможностей меньше. Но более длинные идентификаторы потребляют больше памяти и пропускной способности. Большой набор символов помогает, Но может вызвать проблемы с кодировкой, если идентификаторы включены в URL-адреса или повторно введены вручную.

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

использовать в качестве идентификаторов объектов

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

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

необходимо также позаботиться об использовании идентификаторов, которые достаточно длинны, чтобы сделать коллизии маловероятными, учитывая ожидаемое общее количество идентификаторов. Это называется парадоксом дня рождения."вероятность столкновения, p, примерно n2/(2-й кварталx), где n - это количество фактически сгенерированных идентификаторов,q - число различных символов в алфавит и x - длина идентификаторов. Это должно быть очень небольшое число, например 2-50 или меньше.

разработка этого показывает, что вероятность столкновения между 500k 15-символьными идентификаторами составляет около 2-52, что, вероятно, менее вероятно, чем необнаруженные ошибки от космических лучей и т. д.

сравнение с UUIDs

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

UUID в их стандартном формате занимают много места: 36 символов только для 122 бит энтропии. (Не все биты "случайного" UUID выбираются случайным образом.) Случайно выбранная буквенно-цифровая строка упаковывает больше энтропии всего в 21 символ.

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


Java предоставляет способ сделать это напрямую. Если вы не хотите тире,их легко удалить. Просто используйте uuid.replace("-", "")

import java.util.UUID;

public class randomStringGenerator {
    public static void main(String[] args) {
        System.out.println(generateString());
    }

    public static String generateString() {
        String uuid = UUID.randomUUID().toString();
        return "uuid = " + uuid;
    }
}

выход:

uuid = 2d7428a6-b58c-4008-8575-f05549f16316

static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static SecureRandom rnd = new SecureRandom();

String randomString( int len ){
   StringBuilder sb = new StringBuilder( len );
   for( int i = 0; i < len; i++ ) 
      sb.append( AB.charAt( rnd.nextInt(AB.length()) ) );
   return sb.toString();
}

Если вы счастливы использовать классы Apache, вы можете использовать org.apache.commons.text.RandomStringGenerator (commons-text).

пример:

RandomStringGenerator randomStringGenerator =
        new RandomStringGenerator.Builder()
                .withinRange('0', 'z')
                .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
                .build();
randomStringGenerator.generate(12); // toUpperCase() if you want

начиная с commons-lang 3.6,RandomStringUtils устарела.


в одну строку:

Long.toHexString(Double.doubleToLongBits(Math.random()));

http://mynotes.wordpress.com/2009/07/23/java-generating-random-string/


вы можете использовать библиотеку Apache для этого: RandomStringUtils

RandomStringUtils.randomAlphanumeric(20).toUpperCase();

используя доллар должно быть просто, как:

// "0123456789" + "ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();

String randomString(int length) {
    return $(validCharacters).shuffle().slice(length).toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int i : $(5)) {
        System.out.println(randomString(12));
    }
}

Он выводит что-то вроде этого:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

это легко достижимо без каких-либо внешних библиотек.

1. Криптографическая Генерация Псевдослучайных Данных

сначала вам нужен криптографический PRNG. Java имеет SecureRandom для этого обычно используется лучший источник энтропии на машине (например,/dev/random) . подробнее здесь.

SecureRandom rnd = new SecureRandom();
byte[] token = new byte[byteLength];
rnd.nextBytes(token);

Примечание: SecureRandom - самый медленный, но самый безопасный способ генерации случайных байтов в Java. Я делаю однако не рекомендуется рассматривать производительность здесь, поскольку она обычно не оказывает реального влияния на ваше приложение, если вам не нужно генерировать миллионы токенов в секунду.

2. Требуемое пространство возможных значений

Далее вам нужно решить, "насколько уникальным" должен быть ваш токен. Весь и единственный смысл рассмотрения энтропии - убедиться, что система может противостоять атакам грубой силы: пространство возможных значений должно быть настолько большим, что любой злоумышленник может только попробовать ничтожная доля значений в несмешное время1. Уникальные идентификаторы, такие как случайный UUID у 122bit энтропии (т. е. 2^122 = 5.3x10^36) - вероятность столкновения равна" *(...) для того, чтобы был один шанс на миллиард дублирования, 103 триллиона uuids версии 4 должны быть сгенерированы2". мы выберем 128 бит, так как он точно вписывается в 16 байт и видел как высоко достаточно!--29--> для того, чтобы быть уникальным в основном для каждого, но наиболее экстремальных случаев использования, и вам не нужно думать о дубликатах. Вот простая таблица сравнения энтропии, включая простой анализ проблема с Днем рождения.

comparison of token sizes

для простых требований может хватить длины 8 или 12 байт, но с 16 байтами вы находитесь на "безопасной стороне".

и это в основном его. Последняя вещь подумать о кодировке, чтобы ее можно было представить в виде печатного текста (read, a String).

3. Двоичная кодировка в текст

типичные кодировки включают:

  • Base64 каждый символ кодирует 6 бит, создавая 33% накладных расходов. К сожалению, в JDK (7 и ниже - есть Android и Java 8+). Но!--85-->многочисленные библиотеки exist что добавить. Недостатком является то, что стандарт Base64 небезопасно, например. URL и как имя файла в большинстве файловых систем, требующих дополнительной кодировки (например,кодировка url) или URL безопасная версия Base64 используется. Пример кодирования 16 байт с прокладкой: XfJhfv3C0P6ag7y9VQxSbw==

  • Base32 каждый символ кодирует 5 бит, создавая 40% накладных расходов. Это будет использовать A-Z и 2-7 создание разумного пространства эффективен, будучи нечувствительным к регистру буквенно-цифровым. Нет стандартная реализация в JDK. Пример кодирования 16 байт без подклада: WUPIL5DQTZGMF4D3NX5L7LNFOY

  • Base16 (hex) каждый символ кодирует 4bit, требуя 2 символа на байт(т. е. 16 байт создайте строку длиной 32). Поэтому hex менее эффективен в пространстве, чем Base32 но безопасен для использования в большинстве случаев (url), так как он использует только 0-9 и A to F. Пример кодирования 16 байт: 4fa3dd0f57cb3bf331441ed285b27735. см. обсуждение SO о преобразовании в hex здесь.

дополнительные кодировки, такие как Base85 и экзотической Base122 существуют с лучшей / худшей эффективностью пространства. Вы можете создать свою собственную кодировку (что в основном делает большинство ответов в этом потоке), но я бы не советовал, Если у вас нет очень конкретных требований. См.больше схем кодирования в Википедии статья.

4. Резюме и пример

  • использовать SecureRandom
  • используйте не менее 16 байт (2^128) возможных значений
  • кодируйте согласно вашим требованиям (обычно hex или base32 если вам нужно, чтобы он был буквенно-цифровым)

не

  • ... используйте кодировку домашнего пива:лучше ремонтопригодный и читаемый для других, если они видят, что стандартная кодировка, которую вы используете вместо weird для циклов, создающих символы одновременно.
  • ... используйте UUID:вы тратите 6 бит энтропии и имеете подробное строковое представление

Пример: Генератор Шестнадцатеричных Токенов

public static String generateRandomHexToken(int byteLength) {
    SecureRandom secureRandom = new SecureRandom();
    byte[] token = new byte[byteLength];
    secureRandom.nextBytes(token);
    return new BigInteger(1, token).toString(16); //hex encoding
}

//generateRandomHexToken(16) -> 2189df7475e96aa3982dbeab266497cd

Пример: Tool

если вы хотите готовый к использованию инструмент cli вы можете использовать кости:https://github.com/patrickfav/dice


удивительно, что никто здесь не предложил это, но:

import java.util.UUID

UUID.randomUUID().toString();

легко.

преимущество этого UUIDs приятно и долго и гарантированно будет почти невозможно столкнуться.

Википедия имеет хорошее объяснение этого:

" ...только после генерации 1 миллиарда UUIDs каждую секунду в течение следующих 100 лет вероятность создания только одного дубликата будет около 50%."

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

первые 4 бита - это тип версии и 2 для варианта, поэтому вы получаете 122 бита случайных. Так что если вы хочу чтобы вы могли усечь с конца, чтобы уменьшить размер UUID. Это не рекомендуется, но у вас все еще есть нагрузки случайности, достаточно для ваших записей 500k легко.


вот он на Java:

import static java.lang.Math.round;
import static java.lang.Math.random;
import static java.lang.Math.pow;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static org.apache.commons.lang.StringUtils.leftPad

public class RandomAlphaNum {
  public static String gen(int length) {
    StringBuffer sb = new StringBuffer();
    for (int i = length; i > 0; i -= 12) {
      int n = min(12, abs(i));
      sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0'));
    }
    return sb.toString();
  }
}

вот пример запуска:

scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy

короткое и простое решение, но используются только строчные буквы и цифры:

Random r = new java.util.Random ();
String s = Long.toString (r.nextLong () & Long.MAX_VALUE, 36);

размер составляет около 12 цифр до основания 36 и не может быть улучшен дальше, таким образом. Конечно, вы можете добавить несколько экземпляров.


альтернативой в Java 8 является:

static final Random random = new Random(); // Or SecureRandom
static final int startChar = (int) '!';
static final int endChar = (int) '~';

static String randomString(final int maxLength) {
  final int length = random.nextInt(maxLength + 1);
  return random.ints(length, startChar, endChar + 1)
        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
        .toString();
}

public static String generateSessionKey(int length){
String alphabet = 
        new String("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); //9
int n = alphabet.length(); //10

String result = new String(); 
Random r = new Random(); //11

for (int i=0; i<length; i++) //12
    result = result + alphabet.charAt(r.nextInt(n)); //13

return result;
}

использование UUIDs небезопасно, потому что части UUID не случайны вообще. Процедура @erickson очень аккуратна, но не создает строки одинаковой длины. Следующий фрагмент должен быть достаточным:

/*
 * The random generator used by this class to create random keys.
 * In a holder class to defer initialization until needed.
 */
private static class RandomHolder {
    static final Random random = new SecureRandom();
    public static String randomKey(int length) {
        return String.format("%"+length+"s", new BigInteger(length*5/*base 32,2^5*/, random)
            .toString(32)).replace('\u0020', '0');
    }
}

Почему выбирают length*5. Предположим простой случай случайной строки длины 1, поэтому один случайный символ. Чтобы получить случайный символ, содержащий все цифры 0-9 и символы a-z, нам понадобится случайное число от 0 до 35, чтобы получить один из каждого характер. BigInteger предоставляет конструктор для генерации случайного числа, равномерно распределенного по диапазону 0 to (2^numBits - 1). К сожалению, 35-это не число, которое может быть получено 2^numBits - 1. Таким образом, у нас есть два варианта: либо пойти с 2^5-1=31 или 2^6-1=63. Если бы мы выбрали 2^6 мы получим много "ненужных" / "более длинных" номеров. Поэтому 2^5 является лучшим вариантом, даже если мы теряем 4 символа (w-z). Чтобы создать строку определенной длины, мы можем просто использовать 2^(length*numBits)-1 количество. Этот последняя проблема, если мы хотим строку с определенной длиной, random может генерировать небольшое число, поэтому длина не выполняется, поэтому мы должны поместить строку в требуемую длину, предваряющую нули.


import java.util.Random;

public class passGen{
    //Verison 1.0
    private static final String dCase = "abcdefghijklmnopqrstuvwxyz";
    private static final String uCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String sChar = "!@#$%^&*";
    private static final String intChar = "0123456789";
    private static Random r = new Random();
    private static String pass = "";

    public static void main (String[] args) {
        System.out.println ("Generating pass...");
        while (pass.length () != 16){
            int rPick = r.nextInt(4);
            if (rPick == 0){
                int spot = r.nextInt(25);
                pass += dCase.charAt(spot);
            } else if (rPick == 1) {
                int spot = r.nextInt (25);
                pass += uCase.charAt(spot);
            } else if (rPick == 2) {
                int spot = r.nextInt (7);
                pass += sChar.charAt(spot);
            } else if (rPick == 3){
                int spot = r.nextInt (9);
                pass += intChar.charAt (spot);
            }
        }
        System.out.println ("Generated Pass: " + pass);
    }
}

Так что это просто добавляет пароль в строку и ... да, работает хорошо проверить это... очень просто. Я написал это!--2-->


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

/**
 * Generate a random hex encoded string token of the specified length
 *  
 * @param length
 * @return random hex string
 */
public static synchronized String generateUniqueToken(Integer length){ 
    byte random[] = new byte[length];
    Random randomGenerator = new Random();
    StringBuffer buffer = new StringBuffer();

    randomGenerator.nextBytes(random);

    for (int j = 0; j < random.length; j++) {
        byte b1 = (byte) ((random[j] & 0xf0) >> 4);
        byte b2 = (byte) (random[j] & 0x0f);
        if (b1 < 10)
            buffer.append((char) ('0' + b1));
        else
            buffer.append((char) ('A' + (b1 - 10)));
        if (b2 < 10)
            buffer.append((char) ('0' + b2));
        else
            buffer.append((char) ('A' + (b2 - 10)));
    }
    return (buffer.toString());
}

@Test
public void testGenerateUniqueToken(){
    Set set = new HashSet();
    String token = null;
    int size = 16;

    /* Seems like we should be able to generate 500K tokens 
     * without a duplicate 
     */
    for (int i=0; i<500000; i++){
        token = Utility.generateUniqueToken(size);

        if (token.length() != size * 2){
            fail("Incorrect length");
        } else if (set.contains(token)) {
            fail("Duplicate token generated");
        } else{
            set.add(token);
        }
    }
}

import java.util.Date;
import java.util.Random;

public class RandomGenerator {

  private static Random random = new Random((new Date()).getTime());

    public static String generateRandomString(int length) {
      char[] values = {'a','b','c','d','e','f','g','h','i','j',
               'k','l','m','n','o','p','q','r','s','t',
               'u','v','w','x','y','z','0','1','2','3',
               '4','5','6','7','8','9'};

      String out = "";

      for (int i=0;i<length;i++) {
          int idx=random.nextInt(values.length);
          out += values[idx];
      }
      return out;
    }
}

  1. изменить строковые символы в соответствии с вашими требованиями.

  2. строка неизменяема. Вот!--1--> более эффективно, чем конкатенация строк.


public static String getRandomString(int length) {
       final String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+";
       StringBuilder result = new StringBuilder();
       while(length > 0) {
           Random rand = new Random();
           result.append(characters.charAt(rand.nextInt(characters.length())));
           length--;
       }
       return result.toString();
    }

import java.util.*;
import javax.swing.*;
public class alphanumeric{
    public static void main(String args[]){
        String nval,lenval;
        int n,len;

        nval=JOptionPane.showInputDialog("Enter number of codes you require : ");
        n=Integer.parseInt(nval);

        lenval=JOptionPane.showInputDialog("Enter code length you require : ");
        len=Integer.parseInt(lenval);

        find(n,len);

    }
    public static void find(int n,int length) {
        String str1="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuilder sb=new StringBuilder(length);
        Random r = new Random();

        System.out.println("\n\t Unique codes are \n\n");
        for(int i=0;i<n;i++){
            for(int j=0;j<length;j++){
                sb.append(str1.charAt(r.nextInt(str1.length())));
            }
            System.out.println("  "+sb.toString());
            sb.delete(0,length);
        }
    }
}

на самом деле не нравится ни один из этих ответов относительно "простого" решения :S

Я бы пошел на простой;), чистый java, один лайнер (энтропия основана на случайной длине строки и заданном наборе символов):

public String randomString(int length, String characterSet) {
    return IntStream.range(0, length).map(i -> new SecureRandom().nextInt(characterSet.length())).mapToObj(randomInt -> characterSet.substring(randomInt, randomInt + 1)).collect(Collectors.joining());
}

@Test
public void buildFiveRandomStrings() {
    for (int q = 0; q < 5; q++) {
        System.out.println(randomString(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));//charachterSet can basically be anything
    }
}

или (немного более читаемый старый способ)

public String randomString(int length, String characterSet) {
    StringBuilder sb = new StringBuilder(); //consider using StringBuffer if needed
    for (int i = 0; i < length; i++) {
        int randomInt = new SecureRandom().nextInt(characterSet.length());
        sb.append(characterSet.substring(randomInt, randomInt + 1));
    }
    return sb.toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int q = 0; q < 5; q++) {
        System.out.println(randomString(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")); //charachterSet can basically be anything
    }
}

но с другой стороны, вы также можете пойти с UUID, который имеет довольно хорошую энтропию (https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions):

UUID.randomUUID().toString().replace("-", "")

надеюсь, что это поможет.


вот это решение Scala:

(for (i <- 0 until rnd.nextInt(64)) yield { 
  ('0' + rnd.nextInt(64)).asInstanceOf[Char] 
}) mkString("")

вы можете использовать класс UUID с его сообщением getLeastSignificantBits (), чтобы получить 64 бит случайных данных,а затем преобразовать его в число radix 36 (т. е. строку, состоящую из 0-9, A-Z):

Long.toString(Math.abs( UUID.randomUUID().getLeastSignificantBits(), 36));

Это дает строку длиной до 13 символов. Мы используем математику.abs (), чтобы убедиться, что нет знака минус.


вы можете использовать следующий код , если ваш пароль содержит цифры обязательное буквенные специальных символов:

private static final String NUMBERS = "0123456789";
private static final String UPPER_ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWER_ALPHABETS = "abcdefghijklmnopqrstuvwxyz";
private static final String SPECIALCHARACTERS = "@#$%&*";
private static final int MINLENGTHOFPASSWORD = 8;

public static String getRandomPassword() {
    StringBuilder password = new StringBuilder();
    int j = 0;
    for (int i = 0; i < MINLENGTHOFPASSWORD; i++) {
        password.append(getRandomPasswordCharacters(j));
        j++;
        if (j == 3) {
            j = 0;
        }
    }
    return password.toString();
}

private static String getRandomPasswordCharacters(int pos) {
    Random randomNum = new Random();
    StringBuilder randomChar = new StringBuilder();
    switch (pos) {
        case 0:
            randomChar.append(NUMBERS.charAt(randomNum.nextInt(NUMBERS.length() - 1)));
            break;
        case 1:
            randomChar.append(UPPER_ALPHABETS.charAt(randomNum.nextInt(UPPER_ALPHABETS.length() - 1)));
            break;
        case 2:
            randomChar.append(SPECIALCHARACTERS.charAt(randomNum.nextInt(SPECIALCHARACTERS.length() - 1)));
            break;
        case 3:
            randomChar.append(LOWER_ALPHABETS.charAt(randomNum.nextInt(LOWER_ALPHABETS.length() - 1)));
            break;
    }
    return randomChar.toString();

}

вот код одной строки по AbacusUtil

String.valueOf(CharStream.random('0', 'z').filter(c -> N.isLetterOrDigit(c)).limit(12).toArray())

Random не означает, что он должен быть уникальным. чтобы получить уникальные строки, используйте:

N.uuid() // e.g.: "e812e749-cf4c-4959-8ee1-57829a69a80f". length is 36.
N.guid() // e.g.: "0678ce04e18945559ba82ddeccaabfcd". length is 32 without '-'

вы упоминаете "простой", но на всякий случай, если кто-то еще ищет что-то, что соответствует более строгим требованиям безопасности, вы можете взглянуть на jpwgen. jpwgen моделируется после pwgen в Unix, и очень хорошо настраивается.


public static String randomSeriesForThreeCharacter() {
    Random r = new Random();
    String value="";
    char random_Char ;
    for(int i=0; i<10;i++)
    { 
        random_Char = (char) (48 + r.nextInt(74));
        value=value+random_char;
    }
    return value;
}

используя библиотеку apache, это можно сделать в одной строке

import org.apache.commons.lang.RandomStringUtils;
RandomStringUtils.randomAlphanumeric(64);

вот doc http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/RandomStringUtils.html


может быть, это полезно

package password.generater;

import java.util.Random;

/**
 *
 * @author dell
 */
public class PasswordGenerater {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        int length= 11;
        System.out.println(generatePswd(length));

        // TODO code application logic here
    }
    static char[] generatePswd(int len){
        System.out.println("Your Password ");
        String charsCaps="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
        String Chars="abcdefghijklmnopqrstuvwxyz";
        String nums="0123456789";
        String symbols="!@#$%^&*()_+-=.,/';:?><~*/-+";
        String passSymbols=charsCaps + Chars + nums +symbols;
        Random rnd=new Random();
        char[] password=new char[len];

        for(int i=0; i<len;i++){
            password[i]=passSymbols.charAt(rnd.nextInt(passSymbols.length()));
        }
      return password;

    }
}

Лучший Метод Генератора Случайных Строк

public class RandomStringGenerator{

    private static int randomStringLength = 25 ;
    private static boolean allowSpecialCharacters = true ;
    private static String specialCharacters = "!@$%*-_+:";
    private static boolean allowDuplicates = false ;

    private static boolean isAlphanum = false;
    private static boolean isNumeric = false;
    private static boolean isAlpha = false;
    private static final String alphabet = "abcdefghijklmnopqrstuvwxyz";
    private static boolean mixCase = false;
    private static final String capAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String num = "0123456789";

    public static String getRandomString() {
        String returnVal = "";
        int specialCharactersCount = 0;
        int maxspecialCharacters = randomStringLength/4;

        try {
            StringBuffer values = buildList();
            for (int inx = 0; inx < randomStringLength; inx++) {
                int selChar = (int) (Math.random() * (values.length() - 1));
                if (allowSpecialCharacters)
                {
                    if (specialCharacters.indexOf("" + values.charAt(selChar)) > -1)
                    {
                        specialCharactersCount ++;
                        if (specialCharactersCount > maxspecialCharacters)
                        {
                            while (specialCharacters.indexOf("" + values.charAt(selChar)) != -1)
                            {
                                selChar = (int) (Math.random() * (values.length() - 1));
                            }
                        }
                    }
                }
                returnVal += values.charAt(selChar);
                if (!allowDuplicates) {
                    values.deleteCharAt(selChar);
                }
            }
        } catch (Exception e) {
            returnVal = "Error While Processing Values";
        }
        return returnVal;
    }

    private static StringBuffer buildList() {
        StringBuffer list = new StringBuffer(0);
        if (isNumeric || isAlphanum) {
            list.append(num);
        }
        if (isAlpha || isAlphanum) {
            list.append(alphabet);
            if (mixCase) {
                list.append(capAlpha);
            }
        }
        if (allowSpecialCharacters)
        {
            list.append(specialCharacters);
        }
        int currLen = list.length();
        String returnVal = "";
        for (int inx = 0; inx < currLen; inx++) {
            int selChar = (int) (Math.random() * (list.length() - 1));
            returnVal += list.charAt(selChar);
            list.deleteCharAt(selChar);
        }
        list = new StringBuffer(returnVal);
        return list;
    }   

}

public static String getRandomString(int length) 
{
   String randomStr = UUID.randomUUID().toString();
   while(randomStr.length() < length) {
       randomStr += UUID.randomUUID().toString();
   }
   return randomStr.substring(0, length);
}