Algorithmus
Um eine zufällige Zeichenkette zu erzeugen, fügen Sie Zeichen aus der Menge der zulässigen Symbole nach dem Zufallsprinzip aneinander, bis die Zeichenkette die gewünschte Länge erreicht.
Umsetzung
Hier ist ein relativ einfacher und sehr flexibler Code zur Erzeugung von Zufallsidentifikatoren. Lesen Sie die folgenden Informationen für wichtige Anwendungshinweise.
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);
}
}
Beispiele für den Gebrauch
Erstellen Sie einen unsicheren Generator für 8-stellige Kennungen:
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
Erstellen Sie einen sicheren Generator für Sitzungskennungen:
RandomString session = new RandomString();
Erstellen Sie einen Generator mit leicht lesbaren Codes für den Druck. Die Zeichenfolgen sind länger als vollständige alphanumerische Zeichenfolgen, um die Verwendung weniger Symbole auszugleichen:
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
Verwendung als Sitzungskennzeichen
Es reicht nicht aus, Sitzungskennungen zu generieren, die wahrscheinlich eindeutig sind, oder einen einfachen Zähler zu verwenden. Angreifer kapern Sitzungen, wenn vorhersehbare Bezeichner verwendet werden.
Es besteht ein Spannungsverhältnis zwischen Länge und Sicherheit. Kürzere Kennungen sind leichter zu erraten, weil es weniger Möglichkeiten gibt. Längere Bezeichner verbrauchen jedoch mehr Speicherplatz und Bandbreite. Ein größerer Satz von Symbolen ist hilfreich, kann aber zu Verschlüsselungsproblemen führen, wenn Bezeichner in URLs enthalten sind oder von Hand neu eingegeben werden.
Die zugrundeliegende Zufallsquelle oder Entropie für Sitzungskennungen sollte von einem Zufallszahlengenerator stammen, der für die Kryptografie entwickelt wurde. Die Initialisierung dieser Generatoren kann jedoch manchmal rechenintensiv oder langsam sein, so dass man sich bemühen sollte, sie nach Möglichkeit wiederzuverwenden.
Verwendung als Objektbezeichner
Nicht jede Anwendung erfordert Sicherheit. Die zufällige Zuweisung kann eine effiziente Möglichkeit für mehrere Entitäten sein, Identifikatoren in einem gemeinsam genutzten Raum ohne Koordination oder Partitionierung zu erzeugen. Die Koordinierung kann langsam sein, insbesondere in einer geclusterten oder verteilten Umgebung, und die Aufteilung eines Raums führt zu Problemen, wenn die Anteile der Entitäten zu klein oder zu groß sind.
Bezeichner, die ohne Maßnahmen zur Unvorhersehbarkeit generiert werden, sollten auf andere Weise geschützt werden, wenn ein Angreifer in der Lage sein könnte, sie einzusehen und zu manipulieren, wie es bei den meisten Webanwendungen der Fall ist. Es sollte ein separates Autorisierungssystem geben, das Objekte schützt, deren Bezeichner von einem Angreifer ohne Zugriffserlaubnis erraten werden können.
Es muss auch darauf geachtet werden, dass die Kennungen lang genug sind, um angesichts der zu erwartenden Gesamtzahl der Kennungen Kollisionen unwahrscheinlich zu machen. Dies wird als "Geburtstagsparadoxon" bezeichnet. Die Wahrscheinlichkeit eines Zusammenstoßes, p ist ungefähr n 2 /(2q x ), wobei n ist die Anzahl der tatsächlich erzeugten Identifikatoren, q die Anzahl der unterschiedlichen Symbole im Alphabet ist, und x ist die Länge der Identifikatoren. Dies sollte eine sehr kleine Zahl sein, etwa 2 50 oder weniger.
Daraus ergibt sich, dass die Wahrscheinlichkeit einer Kollision zwischen 500k 15-Zeichen-Kennungen etwa 2 % beträgt. 52 was wahrscheinlich unwahrscheinlicher ist als unentdeckte Fehler durch kosmische Strahlung usw.
Vergleich mit UUIDs
Gemäß ihrer Spezifikation, UUIDs nicht darauf ausgelegt sind, unberechenbar zu sein, und sollte nicht als Sitzungsbezeichner verwendet werden.
UUIDs in ihrem Standardformat benötigen viel Platz: 36 Zeichen für nur 122 Bits Entropie. (Nicht alle Bits einer "zufälligen" UUID werden nach dem Zufallsprinzip ausgewählt.) Eine zufällig ausgewählte alphanumerische Zeichenfolge bietet mehr Entropie in nur 21 Zeichen.
UUIDs sind nicht flexibel; sie haben eine standardisierte Struktur und ein standardisiertes Layout. Dies ist sowohl ihr größter Vorteil als auch ihre größte Schwäche. Bei der Zusammenarbeit mit einer externen Partei kann die Standardisierung, die UUIDs bieten, hilfreich sein. Für den rein internen Gebrauch können sie jedoch ineffizient sein.
166 Stimmen
Vorsicht das Geburtstagsparadoxon .
64 Stimmen
Selbst wenn man das Geburtstagsparadoxon in Betracht zieht, bräuchte man bei Verwendung von 12 alphanumerischen Zeichen (62 insgesamt) immer noch weit über 34 Milliarden Zeichenfolgen, um das Paradoxon zu erreichen. Und das Geburtstagsparadoxon garantiert sowieso keine Kollision, es sagt nur, dass die Wahrscheinlichkeit über 50 % liegt.
6 Stimmen
@NullUserException 50 % Erfolgschance (pro Versuch) ist verdammt hoch: Selbst bei 10 Versuchen liegt die Erfolgsquote bei 0,999. Wenn man das und die Tatsache bedenkt, dass man innerhalb von 24 Stunden VIELE Versuche machen kann, braucht man keine 34 Milliarden Zeichenfolgen, um ziemlich sicher zu sein, dass man mindestens eine davon errät. Das ist der Grund, warum einige Sitzungs-Tokens sehr, sehr lang sein sollten.
0 Stimmen
Dieser Blogpost sollte nützlich sein - Code zur Erzeugung alphanumerischer Zeichenfolgen: rationaljava.com/2015/06/
20 Stimmen
Diese 3 einzeiligen Codes sind sehr nützlich, schätze ich.
Long.toHexString(Double.doubleToLongBits(Math.random()));
UUID.randomUUID().toString();
RandomStringUtils.randomAlphanumeric(12);
26 Stimmen
@Pijusn Ich weiß, das ist alt, aber... die "50% Chance" im Geburtstagsparadoxon ist NO "pro Versuch", das heißt "50 % Wahrscheinlichkeit, dass von (in diesem Fall) 34 Milliarden Zeichenfolgen mindestens ein Paar Dubletten vorhanden ist". Sie bräuchten 1,6 sept illionen - 1,6e21 - Einträge in Ihrer Datenbank, um eine Chance von 50% pro Versuch zu haben.
0 Stimmen
Es ist besser, die
"-"
in der Zeichenkette0 Stimmen
Zufällige Zeichenkette mit Javascript, Java, Python, Rust, Bash