57 votes

Comment créer une chaîne aléatoire en utilisant PHP ?

Je sais que la fonction rand de PHP génère des nombres entiers aléatoires, mais quel est le meilleur moyen de générer une chaîne aléatoire telle que :

Chaîne originale, 9 caractères

$string = 'abcdefghi';

Exemple de chaîne aléatoire limitée à 6 caractères

$string = 'ibfeca';

MISE À JOUR : J'ai trouvé des tonnes de ce type de fonctions, j'essaie essentiellement de comprendre la logique derrière chaque étape.

MISE À JOUR : La fonction doit générer n'importe quel nombre de caractères selon les besoins.

Veuillez commenter les parties si vous répondez.

0 votes

Je ne suis pas sûr de ce que vous voulez, exactement. La chaîne aléatoire doit contenir les lettres de la chaîne d'origine ? Peut-elle utiliser chaque caractère une seule fois ? Et si vous essayez de créer une chaîne aléatoire plus longue que l'originale ?

1 votes

S'agit-il d'une question de type "écrire mon code" ? Qu'est-ce que vous ne comprenez pas dans l'utilisation des nombres aléatoires et que nous pouvons vous aider à apprendre ? Il semble que votre algorithme soit plus spécifique que la simple génération d'une chaîne aléatoire de longueur x.

1 votes

97voto

Gumbo Points 279147

Si vous souhaitez autoriser les occurrences répétitives de caractères, vous pouvez utiliser cette fonction :

function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
    $str = '';
    $count = strlen($charset);
    while ($length--) {
        $str .= $charset[mt_rand(0, $count-1)];
    }
    return $str;
}

L'algorithme de base consiste à générer < longueur > fois un nombre aléatoire entre 0 et < nombre de caractères > - 1 que nous utilisons comme index pour choisir un caractère dans notre ensemble et concaténer ces caractères. Le 0 et le < nombre de caractères Les bornes > - 1 représentent les limites de la $charset car le premier caractère est adressé avec $charset[0] et le dernier avec $charset[count($charset) - 1] .

6 votes

J'aime cette façon, c'est mieux que la solution acceptée, aussi simple que possible, mais vous devriez l'optimiser au minimum en enlevant $count-1 de la boucle et en le mettant au-dessus : $count = strlen($charset) - 1 ;

0 votes

J'aime aussi cette façon de faire ! Très bonne solution, je l'utilise de préférence à la solution acceptée. L'option charset la rend également plus utile.

0 votes

@s3m3n Relisez la réponse acceptée. Le code est le même, il a juste plus de commentaires et utilise plus de variables temporaires :)

92voto

Chad Birch Points 39087

Eh bien, vous n'avez pas clarifié toutes les questions que j'ai posées dans mon commentaire, mais je vais supposer que vous voulez une fonction qui peut prendre une chaîne de caractères "possibles" et une longueur de chaîne à retourner. J'ai commenté en détail comme demandé, en utilisant plus de variables que je le ferais normalement, pour plus de clarté :

function get_random_string($valid_chars, $length)
{
    // start with an empty random string
    $random_string = "";

    // count the number of chars in the valid chars string so we know how many choices we have
    $num_valid_chars = strlen($valid_chars);

    // repeat the steps until we've created a string of the right length
    for ($i = 0; $i < $length; $i++)
    {
        // pick a random number from 1 up to the number of valid chars
        $random_pick = mt_rand(1, $num_valid_chars);

        // take the random character out of the string of valid chars
        // subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
        $random_char = $valid_chars[$random_pick-1];

        // add the randomly-chosen char onto the end of our string so far
        $random_string .= $random_char;
    }

    // return our finished random string
    return $random_string;
}

Pour appeler cette fonction avec les données de votre exemple, vous l'appelleriez de la manière suivante :

$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);

Notez que cette fonction ne vérifie pas l'unicité des caractères valides qui lui sont transmis. Par exemple, si vous l'avez appelée avec une chaîne de caractères valide de 'AAAB' il serait trois fois plus susceptible de choisir un A pour chaque lettre qu'un B. Cela pourrait être considéré comme un bogue ou une fonctionnalité, selon vos besoins.

12 votes

AVERTISSEMENT : Ce code n'est pas sûr car il s'appuie sur mt_rand() qui est vulnérable à de multiples attaques

1 votes

@KeithDonegan Pouvez-vous s'il vous plaît désactiver cette réponse ? C'est incroyablement peu sûr, comme le souligne ircmaxell. Cette réponse est correct.

52voto

tasmaniski Points 1681

Mon préféré :

 echo substr(md5(rand()), 0, 7);

1 votes

Etes-vous sûr des propriétés aléatoires des 7 premiers caractères d'un hash md5 lors du hachage d'entiers convertis en chaînes de caractères ? Je pense qu'il y a trop de facteurs impliqués dans votre code si vous avez besoin d'une bonne distribution aléatoire.

22 votes

OK, ce n'est pas assez bon pour les machines du casino de Las Vegas, mais assez bon pour générer la clé d'enregistrement (par exemple), qui est active 30 minutes sur les sites web.

2 votes

+1 pour la méthode en une ligne, quand on a juste besoin d'une simple chaîne aléatoire sans les protocoles de sécurité de la NSA.

24voto

ircmaxell Points 74865

Alors, laissez-moi commencer par dire UTILISER UNE BIBLIOTHÈQUE . Il en existe plusieurs :

Le cœur du problème est que presque toutes les réponses de cette page sont susceptibles d'être attaquées. mt_rand() , rand() , lcg_value() y uniqid() sont tous vulnérable aux attaques .

Un bon système utilisera /dev/urandom du système de fichiers, ou mcrypt_create_iv() (con MCRYPT_DEV_URANDOM ) ou openssl_pseudo_random_bytes() . Ce que tous les éléments ci-dessus font. PHP 7 sera doté de deux nouvelles fonctions random_bytes($len) y random_int($min, $max) qui sont également sûrs.

Sachez que la plupart de ces fonctions (sauf random_int() ) renvoient des "chaînes brutes", ce qui signifie qu'elles peuvent contenir n'importe quel caractère ASCII de l'une des catégories suivantes 0 - 255 . Si vous voulez une chaîne imprimable, je vous suggère de faire passer le résultat par base64_encode() .

17voto

function generate_random_string($name_length = 8) {
    $alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}

Mise à jour du code selon mzhang dans les commentaires ci-dessous.

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