Как сгенерировать случайную буквенно-цифровую строку
Я искал простой алгоритм Java для генерации псевдослучайной буквенно-цифровой строки. В моей ситуации это использовалось бы как уникальный идентификатор сеанса / ключа, который "вероятно" был бы уникальным в течение 500K+
поколения (мои потребности на самом деле не требуют ничего более сложного).
В идеале я мог бы указать длину в зависимости от моих потребностей в уникальности. Например, сгенерированная строка длиной 12 может выглядеть примерно так "AEYGF7K0DM1X"
.
Переведено автоматически
Ответ 1
Алгоритм
Чтобы сгенерировать случайную строку, объедините символы, выбранные случайным образом из набора допустимых символов, пока строка не достигнет желаемой длины.
Реализация
Вот несколько довольно простых и очень гибких кодов для генерации случайных идентификаторов. Прочтите следующую информацию, чтобы получить важные указания по применению.
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/(2qx), где n - количество фактически сгенерированных идентификаторов, q - количество различных символов в алфавите, а x - длина идентификаторов. Это должно быть очень маленькое число, например 2-50 или меньше.
Анализ этого показывает, что вероятность столкновения 500 тыс. 15-символьных идентификаторов составляет около 2-52, что, вероятно, менее вероятно, чем необнаруженные ошибки от космических лучей и т.д.
Сравнение с UUID
Согласно их спецификации, UUID не предназначены для непредсказуемости и не должны использоваться в качестве идентификаторов сеанса.
UUID в их стандартном формате занимают много места: 36 символов составляют всего 122 бита энтропии. (Не все биты "случайного" UUID выбираются случайным образом.) Случайно выбранная буквенно-цифровая строка содержит больше энтропии всего в 21 символе.
UUID не являются гибкими; они имеют стандартизированную структуру и расположение. Это их главное достоинство, а также их основная слабость. При сотрудничестве с внешней стороной может быть полезна стандартизация, предлагаемая UUID. Для чисто внутреннего использования они могут быть неэффективны.
Ответ 2
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
Ответ 3
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();
}
Ответ 4
Если вам нравится использовать классы Apache, вы могли бы использовать org.apache.commons.text.RandomStringGenerator
(Apache Commons Text).
Пример:
RandomStringGenerator randomStringGenerator =
new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
.build();
randomStringGenerator.generate(12); // toUpperCase() if you want
Начиная с Apache Commons Lang 3.6, RandomStringUtils
не рекомендуется.