Algorithmus
Um eine zufällige Zeichenfolge zu generieren, verketten Sie Zeichen, die zufällig aus dem Satz akzeptabler Symbole gezogen wurden, bis die Zeichenfolge die gewünschte Länge erreicht hat.
Implementierung
Hier ist ein ziemlich einfacher und sehr flexibler Code zum Generieren von zufälligen Bezeichnern. Lesen Sie die folgenden Informationen, um wichtige Anwendungshinweise zu erhalten.
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);
}
}
Anwendungsbeispiele
Erstellen Sie einen unsicheren Generator für 8-stellige Bezeichner:
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
Erstellen Sie einen sicheren Generator für Sitzungskennungen:
RandomString session = new RandomString();
Erstellen Sie einen Generator mit einfach zu lesenden Codes zum Drucken. Die Zeichenfolgen sind länger als vollständige alphanumerische Zeichenfolgen, um die Verwendung weniger Symbole zu kompensieren:
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
Verwendung als Sitzungskennung
Das Generieren von Sitzungskennungen, die wahrscheinlich eindeutig sind, ist nicht gut genug, oder Sie können einfach einen einfachen Zähler verwenden. Angreifer entführen Sitzungen, wenn vorhersehbare Kennungen verwendet werden.
Es gibt Spannungen zwischen Länge und Sicherheit. Kürzere Kennungen sind leichter zu erraten, da weniger Möglichkeiten bestehen. Längere Kennungen verbrauchen jedoch mehr Speicher und Bandbreite. Ein größerer Satz von Symbolen hilft, kann jedoch zu Codierungsproblemen führen, wenn Bezeichner in URLs enthalten sind oder von Hand neu eingegeben werden.
Die zugrunde liegende Quelle für Zufälligkeit oder Entropie für Sitzungskennungen sollte ein Zufallszahlengenerator sein, der für die Kryptographie entwickelt wurde. Das Initialisieren dieser Generatoren kann jedoch manchmal rechenintensiv oder langsam sein. Daher sollten Anstrengungen unternommen werden, um sie nach Möglichkeit wiederzuverwenden.
Verwendung als Objektkennungen
Nicht jede Anwendung erfordert Sicherheit. Die zufällige Zuweisung kann eine effiziente Möglichkeit für mehrere Entitäten sein, Bezeichner in einem gemeinsam genutzten Bereich ohne Koordination oder Partitionierung zu generieren. Die Koordination kann langsam sein, insbesondere in einer Cluster- oder verteilten Umgebung, und die Aufteilung eines Bereichs verursacht Probleme, wenn Entitäten zu kleine oder zu große Freigaben erhalten.
Bezeichner, die generiert werden, ohne Maßnahmen zu ergreifen, um sie unvorhersehbar zu machen, sollten auf andere Weise geschützt werden, wenn ein Angreifer sie möglicherweise anzeigen und bearbeiten kann, wie dies in den meisten Webanwendungen der Fall ist. Es sollte ein separates Autorisierungssystem geben, das Objekte schützt, deren Kennung von einem Angreifer ohne Zugriffsberechtigung erraten werden kann.
Es muss auch darauf geachtet werden, Kennungen zu verwenden, die lang genug sind, um Kollisionen angesichts der erwarteten Gesamtzahl der Kennungen unwahrscheinlich zu machen. Dies wird als "Geburtstagsparadoxon" bezeichnet. Die Wahrscheinlichkeit einer Kollision p beträgt ungefähr n 2 / (2q x ), wobei n die Anzahl der tatsächlich erzeugten Bezeichner ist, q die Anzahl der unterschiedlichen Symbole im Alphabet ist und x die Länge der Bezeichner ist. Dies sollte eine sehr kleine Zahl sein, wie 2 - 50 oder weniger.
Arbeiten dieser heraus zeigt , dass die Wahrscheinlichkeit einer Kollision zwischen 500k 15 Zeichen Bezeichner ist etwa 2 -52 , was wahrscheinlich weniger wahrscheinlich ist als unentdeckte Fehler durch kosmische Strahlung usw.
Vergleich mit UUIDs
Entsprechend ihrer Spezifikation sind UUIDs nicht unvorhersehbar und sollten nicht als Sitzungskennungen verwendet werden.
UUIDs in ihrem Standardformat nehmen viel Platz ein: 36 Zeichen für nur 122 Entropiebits. (Nicht alle Bits einer "zufälligen" UUID werden zufällig ausgewählt.) Eine zufällig ausgewählte alphanumerische Zeichenfolge enthält mehr Entropie in nur 21 Zeichen.
UUIDs sind nicht flexibel. Sie haben eine standardisierte Struktur und ein standardisiertes Layout. Dies ist ihre Haupttugend sowie ihre Hauptschwäche. Bei der Zusammenarbeit mit einer externen Partei kann die von UUIDs angebotene Standardisierung hilfreich sein. Für den rein internen Gebrauch können sie ineffizient sein.