Sto cercando un algoritmo Java semplice per generare una stringa alfa-numerica pseudo-casuale. Nella mia situazione sarebbe usato come un identificatore unico di sessione/chiave che sarebbe "probabile" essere unico su 500K+
generazione (le mie esigenze non richiedono davvero qualcosa di molto più sofisticato).
Idealmente, sarei in grado di specificare una lunghezza a seconda delle mie esigenze di unicità. Per esempio, una stringa generata di lunghezza 12 potrebbe sembrare qualcosa come "AEYGF7K0DM1X"
.
Per generare una stringa casuale, concatenate caratteri presi a caso dall'insieme dei simboli accettabili fino a quando la stringa raggiunge la lunghezza desiderata.
Ecco del codice abbastanza semplice e molto flessibile per generare identificatori casuali. Leggete le informazioni che seguono per importanti note applicative.
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);
}
}
Crea un generatore insicuro per identificatori di 8 caratteri:
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
Creare un generatore sicuro per identificatori di sessione:
RandomString session = new RandomString();
Creare un generatore con codici facili da leggere per la stampa. Le stringhe sono più lunghe delle stringhe alfanumeriche complete per compensare l'uso di meno simboli:
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
Generare identificatori di sessione che probabilmente saranno unici non è abbastanza buono, o si potrebbe semplicemente usare un semplice contatore. Gli attaccanti dirottano le sessioni quando vengono utilizzati identificatori prevedibili.
C'è tensione tra lunghezza e sicurezza. Identificatori più corti sono più facili da indovinare, perché ci sono meno possibilità. Ma gli identificatori più lunghi consumano più memoria e larghezza di banda. Un insieme più ampio di simboli aiuta, ma potrebbe causare problemi di codifica se gli identificatori sono inclusi negli URL o reinseriti a mano.
La fonte sottostante di casualità, o entropia, per gli identificatori di sessione dovrebbe provenire da un generatore di numeri casuali progettato per la crittografia. Tuttavia, l'inizializzazione di questi generatori può a volte essere computazionalmente costosa o lenta, quindi si dovrebbe fare uno sforzo per riutilizzarli quando possibile.
Non tutte le applicazioni richiedono sicurezza. L'assegnazione casuale può essere un modo efficiente per più entità di generare identificatori in uno spazio condiviso senza alcun coordinamento o partizionamento. Il coordinamento può essere lento, specialmente in un ambiente clusterizzato o distribuito, e la suddivisione di uno spazio causa problemi quando le entità finiscono con quote troppo piccole o troppo grandi.
Gli identificatori generati senza prendere misure per renderli imprevedibili dovrebbero essere protetti con altri mezzi se un attaccante potrebbe essere in grado di vederli e manipolarli, come accade nella maggior parte delle applicazioni web. Ci dovrebbe essere un sistema di autorizzazione separato che protegge gli oggetti il cui identificatore può essere indovinato da un attaccante senza permesso di accesso.
Si deve anche fare attenzione ad usare identificatori che siano abbastanza lunghi da rendere improbabili le collisioni dato il numero totale previsto di identificatori. Questo è indicato come "il paradosso del compleanno." La probabilità di una collisione, p, è approssimativamente n2/(2qx), dove n è il numero di identificatori effettivamente generati, q è il numero di simboli distinti nell'alfabeto, e x è la lunghezza degli identificatori. Questo dovrebbe essere un numero molto piccolo, come 2‑50 o meno.
Calcolando questo, la possibilità di collisione tra 500k identificatori di 15 caratteri è circa 2‑52, che è probabilmente meno probabile degli errori non rilevati dai raggi cosmici, ecc.
Secondo le loro specifiche, gli UUID non sono progettati per essere imprevedibili, e non dovrebbero essere usati come identificatori di sessione.
Gli UUID nel loro formato standard occupano molto spazio: 36 caratteri per soli 122 bit di entropia. (Non tutti i bit di un "random" UUID sono selezionati a caso.) Una stringa alfanumerica scelta a caso racchiude più entropia in soli 21 caratteri.
Gli UUID non sono flessibili; hanno una struttura e un layout standardizzati. Questa è la loro principale virtù e anche la loro principale debolezza. Quando si collabora con una parte esterna, la standardizzazione offerta dagli UUID può essere utile. Per un uso puramente interno, possono essere inefficienti.
Java fornisce un modo per farlo direttamente. Se non volete i trattini, sono facili da togliere. Basta usare 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;
}
}
Output:
uuid = 2d7428a6-b58c-4008-8575-f05549f16316
Eccolo in 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();
}
}
Ecco un esempio di esecuzione:
scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy