1931 votes

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

J'ai cherché un simple Algorithme Java permettant de générer une chaîne alphanumérique pseudo-aléatoire. Dans mon cas, cette chaîne serait utilisée comme identifiant unique de la session/clé, qui serait "probablement" unique sur plus d'un million d'ordinateurs. 500K+ (mes besoins ne nécessitent pas vraiment quelque chose de plus sophistiqué).

Idéalement, je pourrais spécifier une longueur en fonction de mes besoins d'unicité. Par exemple, une chaîne générée d'une longueur de 12 pourrait ressembler à ceci "AEYGF7K0DM1X" .

162 votes

Méfiez-vous de le paradoxe de l'anniversaire .

62 votes

Même en tenant compte du paradoxe de l'anniversaire, si vous utilisez 12 caractères alphanumériques (62 au total), il vous faudrait encore bien plus de 34 milliards de chaînes de caractères pour atteindre le paradoxe. Et le paradoxe d'anniversaire ne garantit pas une collision de toute façon, il dit juste qu'il y a plus de 50% de chances.

6 votes

@NullUserException 50 % de chance de succès (par essai) est sacrément élevé : même avec 10 essais, le taux de succès est de 0,999. En gardant cela à l'esprit et le fait que vous pouvez essayer BEAUCOUP sur une période de 24 heures, vous n'avez pas besoin de 34 milliards de chaînes de caractères pour être pratiquement sûr de deviner au moins l'une d'entre elles. C'est la raison pour laquelle certains jetons de session doivent être très, très longs.

32voto

Michael Allen Points 2475

C'est surprenant, personne ici ne l'a suggéré, mais.. :

import java.util.UUID

UUID.randomUUID().toString();

Facile.

L'avantage de cette méthode est que les UUID sont jolis, longs et garantis de ne pas entrer en collision.

Wikipedia a une bonne explication d'elle :

" ...seulement après avoir généré 1 milliard d'UUID chaque seconde pendant les 100 prochaines années, la probabilité de créer un seul doublon serait d'environ 50%."

Les quatre premiers bits sont le type de version et deux pour la variante, vous obtenez donc 122 bits d'aléatoire. Donc si vous veulent vous pouvez tronquer à partir de la fin pour réduire la taille de l'UUID. Ce n'est pas recommandé, mais vous avez toujours beaucoup d'aléatoire, assez pour vos 500 000 enregistrements faciles.

18voto

Howard Lovatt Points 94

Une alternative dans Java 8 est :

static final Random random = new Random(); // Or SecureRandom
static final int startChar = (int) '!';
static final int endChar = (int) '~';

static String randomString(final int maxLength) {
  final int length = random.nextInt(maxLength + 1);
  return random.ints(length, startChar, endChar + 1)
        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
        .toString();
}

12voto

rina Points 21
public static String generateSessionKey(int length){
    String alphabet =
        new String("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); // 9

    int n = alphabet.length(); // 10

    String result = new String();
    Random r = new Random(); // 11

    for (int i=0; i<length; i++) // 12
        result = result + alphabet.charAt(r.nextInt(n)); //13

    return result;
}

11voto

cmpbah Points 21
import java.util.Random;

public class passGen{
    // Version 1.0
    private static final String dCase = "abcdefghijklmnopqrstuvwxyz";
    private static final String uCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String sChar = "!@#$%^&*";
    private static final String intChar = "0123456789";
    private static Random r = new Random();
    private static StringBuilder pass = new StringBuilder();

    public static void main (String[] args) {
        System.out.println ("Generating pass...");
        while (pass.length () != 16){
            int rPick = r.nextInt(4);
            if (rPick == 0){
                int spot = r.nextInt(26);
                pass.append(dCase.charAt(spot));
            } else if (rPick == 1) {
                int spot = r.nextInt(26);
                pass.append(uCase.charAt(spot));
            } else if (rPick == 2) {
                int spot = r.nextInt(8);
                pass.append(sChar.charAt(spot));
            } else {
                int spot = r.nextInt(10);
                pass.append(intChar.charAt(spot));
            }
        }
        System.out.println ("Generated Pass: " + pass.toString());
    }
}

Cela ajoute juste le mot de passe dans la chaîne et... ouais, ça marche bien. Essayez-le... C'est très simple, je l'ai écrit.

11voto

Kristian Kraljic Points 226

L'utilisation des UUID n'est pas sûre, car certaines parties de l'UUID ne sont pas du tout aléatoires. Le site procédure d'erickson est très soigné, mais il ne crée pas de chaînes de même longueur. L'extrait suivant devrait suffire :

/*
 * The random generator used by this class to create random keys.
 * In a holder class to defer initialization until needed.
 */
private static class RandomHolder {
    static final Random random = new SecureRandom();
    public static String randomKey(int length) {
        return String.format("%"+length+"s", new BigInteger(length*5/*base 32,2^5*/, random)
            .toString(32)).replace('\u0020', '0');
    }
}

Pourquoi choisir length*5 ? Supposons le cas simple d'une chaîne aléatoire de longueur 1, donc un caractère aléatoire. Pour obtenir un caractère aléatoire contenant tous les chiffres 0-9 et les caractères a-z, nous aurions besoin d'un nombre aléatoire entre 0 et 35 pour obtenir un de chaque caractère.

BigInteger fournit un constructeur pour générer un nombre aléatoire, uniformément distribué sur l'intervalle 0 to (2^numBits - 1) . Malheureusement, 35 n'est pas un nombre qui peut être reçu par 2^numBits - 1.

Nous avons donc deux options : Soit aller avec 2^5-1=31 o 2^6-1=63 . Si nous choisissions 2^6 nous obtiendrions beaucoup de numéros "inutiles" / "longs". C'est pourquoi 2^5 est la meilleure option, même si nous perdons quatre caractères (w-z). Pour générer maintenant une chaîne de caractères d'une certaine longueur, nous pouvons simplement utiliser une fonction 2^(length*numBits)-1 numéro. Le dernier problème, si nous voulons une chaîne de caractères d'une certaine longueur, le hasard pourrait générer un petit nombre, donc la longueur n'est pas respectée, nous devons donc compléter la chaîne de caractères à sa longueur requise en ajoutant des zéros.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X