Question Comment générer une chaîne alphanumérique aléatoire?


J'ai cherché un simple Algorithme Java pour générer une chaîne alphanumérique pseudo-aléatoire. Dans ma situation, il serait utilisé comme un unique identificateur de session / clé qui serait "probablement" unique sur 500K + génération (mes besoins n'exigent vraiment rien de plus sophistiqué). Idéalement, je serais en mesure de spécifier une longueur en fonction de mes besoins d'unicité. Par exemple, une chaîne générée de longueur 12 peut ressembler à quelque chose comme "AEYGF7K0DM1X".


1458


origine


Réponses:


Algorithme

Pour générer une chaîne aléatoire, concaténez les caractères tirés aléatoirement dans l'ensemble des symboles acceptables jusqu'à ce que la chaîne atteigne la longueur désirée.

la mise en oeuvre

Voici un code assez simple et très flexible pour générer des identifiants aléatoires. Lisez les informations qui suivent pour les notes d'application importantes.

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);
    }

}

Exemples d'utilisation

Créez un générateur non sécurisé pour les identifiants à 8 caractères:

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

Créez un générateur sécurisé pour les identifiants de session:

RandomString session = new RandomString();

Créez un générateur avec des codes faciles à lire pour l'impression. Les chaînes sont plus longues que les chaînes alphanumériques complètes pour compenser l'utilisation de moins de symboles:

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

Utiliser comme identifiants de session

Générer des identifiants de session susceptibles d'être uniques n'est pas suffisant, ou vous pouvez simplement utiliser un simple compteur. Les attaquants piratent les sessions lorsque des identifiants prévisibles sont utilisés.

Il y a une tension entre la longueur et la sécurité. Les identifiants plus courts sont plus faciles à deviner, car il y a moins de possibilités. Mais les identifiants plus longs consomment plus de stockage et de bande passante. Un ensemble plus important de symboles aide, mais pourrait causer des problèmes d'encodage si les identificateurs sont inclus dans les URL ou réinscrits manuellement.

La source sous-jacente du caractère aléatoire, ou entropie, des identificateurs de session devrait provenir d'un générateur de nombres aléatoires conçu pour la cryptographie. Cependant, l'initialisation de ces générateurs peut parfois être coûteuse ou lente en termes de calculs, et il faudrait donc s'efforcer de les réutiliser lorsque cela est possible.

Utiliser comme identifiants d'objet

Toutes les applications ne nécessitent pas de sécurité. L'assignation aléatoire peut être un moyen efficace pour plusieurs entités de générer des identifiants dans un espace partagé sans aucune coordination ou partitionnement. La coordination peut être lente, en particulier dans un environnement en cluster ou distribué, et la division d'un espace entraîne des problèmes lorsque les entités se retrouvent avec des partages trop petits ou trop grands.

Les identificateurs générés sans prendre de mesures pour les rendre imprévisibles doivent être protégés par d'autres moyens si un attaquant peut les voir et les manipuler, comme c'est le cas dans la plupart des applications Web. Il devrait y avoir un système d'autorisation distinct qui protège les objets dont l'identificateur peut être deviné par un attaquant sans autorisation d'accès.

Il faut également prendre soin d'utiliser des identificateurs suffisamment longs pour rendre les collisions improbables compte tenu du nombre total d'identificateurs prévu. C'est ce qu'on appelle "le paradoxe de l'anniversaire". La probabilité d'une collision,  p, est environ n2/ (2qX), où n est le nombre d'identifiants réellement générés, q est le nombre de symboles distincts dans l'alphabet, et X est la longueur des identifiants. Cela devrait être un très petit nombre, comme 2-50 ou moins.

Travailler cela montre que la probabilité de collision entre 500k identifiants de 15 caractères est d'environ 2-52, qui est probablement moins probable que les erreurs non détectées provenant des rayons cosmiques, etc.

Comparaison avec les UUID

Selon leur spécification, les UUID ne sont pas conçus pour être imprévisibles, et ne devrait pas être utilisé comme identifiants de session.

Les UUID dans leur format standard prennent beaucoup d'espace: 36 caractères pour seulement 122 bits d'entropie. (Tous les bits d'un UUID "aléatoire" ne sont pas sélectionnés de manière aléatoire.) Une chaîne alphanumérique choisie au hasard contient plus d'entropie en seulement 21 caractères.

Les UUID ne sont pas flexibles. ils ont une structure et une disposition standardisées. C'est leur principale vertu ainsi que leur principale faiblesse. Lorsque vous collaborez avec une partie extérieure, la normalisation offerte par les UUID peut être utile. Pour une utilisation purement interne, ils peuvent être inefficaces.


1396



Java fournit un moyen de le faire directement. Si vous ne voulez pas les tirets, ils sont faciles à enlever. Juste utiliser 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;
    }
}

Sortie:

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

732



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();
}

468



Si vous êtes heureux d'utiliser les classes Apache, vous pouvez utiliser org.apache.commons.text.RandomStringGenerator (texte commun).

Exemple:

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

Depuis commons-lang 3.6, RandomStringUtils est obsolète.


453



En une ligne:

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

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


90



Vous pouvez utiliser la bibliothèque Apache pour cela: RandomStringUtils

RandomStringUtils.randomAlphanumeric(20).toUpperCase();

87



en utilisant Dollar devrait être simple comme:

// "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));
    }
}

il sort quelque chose comme ça:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

36