PHP: comment générer une chaîne alphanumérique aléatoire et unique?
comment serait-il possible de générer une chaîne de caractères aléatoire et unique en utilisant des nombres et des lettres pour une utilisation dans un lien de vérification? Comme lorsque vous créez un compte sur un site web, et il vous envoie un mail avec un lien, et vous devez cliquer sur ce lien afin de vérifier votre compte...ouais...l'un de ceux-ci.
Comment puis-je générer L'un de ceux utilisant PHP?
mise à Jour: Juste de rappeler à propos de uniqid()
. C'est une fonction PHP qui génère un identifiant unique basé sur le temps courant en microsecondes. Je pense que je vais l'utiliser.
24 réponses
avis de sécurité : cette solution ne doit pas être utilisée dans des situations où la qualité de votre caractère aléatoire peut affecter la sécurité d'une application. En particulier,
rand()
etuniqid()
ne sont pas des générateurs de nombres aléatoires cryptographiquement sûrs . Voir réponse de Scott pour une solution de rechange sécuritaire.
Si vous n'avez pas besoin d'être absolument unique plus heure:
md5(uniqid(rand(), true))
sinon (étant donné que vous avez déjà déterminé un login unique pour votre utilisateur):
md5(uniqid($your_user_login, true))
je cherchais juste comment résoudre ce même problème, mais je veux aussi que ma fonction crée un token qui puisse être utilisé pour la récupération de mot de passe. Cela signifie que je dois limiter la capacité du jeton à être deviné. Parce que uniqid
est basé sur le temps, et selon php.net "la valeur de retour est un peu différent de microtime()", uniqid
ne répond pas aux critères. PHP recommande d'utiliser openssl_random_pseudo_bytes()
à la place pour générer cryptographique sécurisé jetons.
une réponse rapide, brève et directe est:
bin2hex(openssl_random_pseudo_bytes($bytes))
qui générera une chaîne aléatoire de caractères alphanumériques de longueur = $bytes * 2. Malheureusement cela a seulement un alphabet de [a-f][0-9]
, mais cela fonctionne.
Voici la fonction la plus forte que J'ai pu faire qui répond aux critères (C'est une version implémentée de la réponse D'Erik).
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(log($range, 2));
$bytes = (int) ($log / 8) + 1; // length in bytes
$bits = (int) $log + 1; // length in bits
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
$rnd = $rnd & $filter; // discard irrelevant bits
} while ($rnd > $range);
return $min + $rnd;
}
function getToken($length)
{
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
}
return $token;
}
crypto_rand_secure($min, $max)
remplace rand()
ou mt_rand
. Il utilise openssl_random_pseudo_bytes pour aider à créer un nombre aléatoire entre $min et $max.
getToken($length)
crée un alphabet à utiliser dans le jeton, puis crée une chaîne de longueur $length
.
EDIT: j'ai oublié de citer la source http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
EDIT (PHP7): avec la sortie de PHP7, la bibliothèque standard a maintenant deux nouvelles fonctions qui peuvent remplacer/améliorer/simplifier la fonction crypto_rand_secure ci-dessus. random_bytes($length)
et random_int($min, $max)
http://php.net/manual/en/function.random-bytes.php
http://php.net/manual/en/function.random-int.php
exemple:
function getToken($length){
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[random_int(0, $max-1)];
}
return $token;
}
version orientée objet de la solution la plus votée
j'ai créé une solution orientée objet basée sur Scott 'S réponse:
<?php
namespace Utils;
/**
* Class RandomStringGenerator
* @package Utils
*
* Solution taken from here:
* http://stackoverflow.com/a/13733588/1056679
*/
class RandomStringGenerator
{
/** @var string */
protected $alphabet;
/** @var int */
protected $alphabetLength;
/**
* @param string $alphabet
*/
public function __construct($alphabet = '')
{
if ('' !== $alphabet) {
$this->setAlphabet($alphabet);
} else {
$this->setAlphabet(
implode(range('a', 'z'))
. implode(range('A', 'Z'))
. implode(range(0, 9))
);
}
}
/**
* @param string $alphabet
*/
public function setAlphabet($alphabet)
{
$this->alphabet = $alphabet;
$this->alphabetLength = strlen($alphabet);
}
/**
* @param int $length
* @return string
*/
public function generate($length)
{
$token = '';
for ($i = 0; $i < $length; $i++) {
$randomKey = $this->getRandomInteger(0, $this->alphabetLength);
$token .= $this->alphabet[$randomKey];
}
return $token;
}
/**
* @param int $min
* @param int $max
* @return int
*/
protected function getRandomInteger($min, $max)
{
$range = ($max - $min);
if ($range < 0) {
// Not so random...
return $min;
}
$log = log($range, 2);
// Length in bytes.
$bytes = (int) ($log / 8) + 1;
// Length in bits.
$bits = (int) $log + 1;
// Set all lower bits to 1.
$filter = (int) (1 << $bits) - 1;
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
// Discard irrelevant bits.
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return ($min + $rnd);
}
}
Utilisation
<?php
use Utils\RandomStringGenerator;
// Create new instance of generator class.
$generator = new RandomStringGenerator;
// Set token length.
$tokenLength = 32;
// Call method to generate random string.
$token = $generator->generate($tokenLength);
alphabet personnalisé
Vous pouvez utiliser l'alphabet personnalisé si nécessaire. Il suffit de passer une chaîne avec des caractères supportés au constructeur ou au setter:
<?php
$customAlphabet = '0123456789ABCDEF';
// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);
// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);
Voici les échantillons de sortie
SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
j'espère que ça aidera quelqu'un. Acclamations!
cette fonction générera une clé aléatoire en utilisant des nombres et des lettres:
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
echo random_string(50);
exemple de sortie:
zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
je suis en retard mais je suis ici avec de bonnes données de recherche basées sur les fonctions fournies par la réponse de Scott . J'ai donc mis en place une gouttelette D'océan numérique juste pour ce test automatisé de 5 jours et stocké les chaînes uniques générées dans une base de données MySQL.
pendant cette période d'essai, j'ai utilisé 5 longueurs différentes(5, 10, 15, 20, 50) et + / -0,5 millions d'enregistrements ont été insérés pour chaque longueur. Pendant mon test, seulement la longueur 5 généré + / - 3K duplique sur 0,5 million et les longueurs restantes n'ont pas généré de doublons. Donc, nous pouvons dire que si nous utilisons une longueur de 15 ou plus avec les fonctions de Scott, alors nous pouvons générer des chaînes uniques très fiables. Voici le tableau montrant mes données de recherche:
j'espère que cela aidera.
vous pouvez utiliser UUID(Universally Unique Identifier), il peut être utilisé à toutes fins, de la chaîne d'authentification de l'utilisateur à l'id de transaction de paiement.
un UUID est un nombre de 16 octets (128 bits). Sous sa forme canonique, un UUID est représenté par 32 chiffres hexadécimaux, présentés en cinq groupes séparés par des traits d'Union, Sous la forme 8-4-4-4-12 pour un total de 36 caractères (32 caractères alphanumériques et quatre traits d'Union).
function generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0C2f ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
);
}
//appel de fonction
$transationID = generate_uuid();
quelques exemples de sorties seront comme:
E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2
espère que cela aide quelqu'un dans le futur :)
j'utilise cette doublure:
base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
où la longueur est la longueur de la chaîne désirée (divisible par 4, sinon elle est arrondie au chiffre inférieur le plus proche divisible par 4)
- générer un nombre aléatoire en utilisant votre nombre aléatoire préféré générateur
- multipliez et divisez-le pour obtenir un nombre correspondant au nombre des caractères dans votre alphabet de code
- Obtenir l'élément à l'index ton alphabet codé.
- répétez à partir de 1) jusqu'à ce que vous ayez la longueur vous want
E. g (en pseudo-code)
int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
utilisez le code ci-dessous pour générer le nombre aléatoire de 11 caractères ou changer le nombre selon votre exigence.
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
or we can use custom function to generate the random number
function randomNumber($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
//generate random number
$randomNum=randomNumber(11);
Voici ultime générateur d'id unique pour vous. faite par moi.
<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un= uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.
echo $mdun;
?>
vous pouvez faire écho à n'importe quel " var " pour votre id comme vous voulez. mais $ mdun est mieux, vous pouvez remplacer md5 à sha1 pour un meilleur code, mais ce sera très long, ce dont vous n'avez peut-être pas besoin.
Merci.
voici ce que j'utilise:
md5(time() . rand());
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
j'aime utiliser des clés de hachage lors de la négociation de liens de vérification. Je recommande d'utiliser le microtime et le hachage que L'utilisation de MD5 car il ne devrait pas y avoir de raison pour que les clés devraient être les mêmes, car il se hasarde basé sur off du microtime.
-
$key = md5(rand());
-
$key = md5(microtime());
function random_string($length = 8) {
$alphabets = range('A','Z');
$numbers = range('0','9');
$additional_characters = array('_','=');
$final_array = array_merge($alphabets,$numbers,$additional_characters);
while($length--) {
$key = array_rand($final_array);
$password .= $final_array[$key];
}
if (preg_match('/[A-Za-z0-9]/', $password))
{
return $password;
}else{
return random_string();
}
}
Scott, oui vous êtes très à l'écriture et à la bonne solution! Grâce.
je suis également tenu de générer un jeton API unique pour chaque utilisateur. Suivant mon approche, j'ai utilisé les informations utilisateur (Userid et Username):
public function generateUniqueToken($userid, $username){
$rand = mt_rand(100,999);
$md5 = md5($userid.'!(&^ 532567_465 ///'.$username);
$md53 = substr($md5,0,3);
$md5_remaining = substr($md5,3);
$md5 = $md53. $rand. $userid. $md5_remaining;
return $md5;
}
s'il vous Plaît jetez un oeil et laissez-moi savoir si toute amélioration que je peux faire. Merci
après avoir lu les exemples précédents, j'ai trouvé ceci:
protected static $nonce_length = 32;
public static function getNonce()
{
$chars = array();
for ($i = 0; $i < 10; $i++)
$chars = array_merge($chars, range(0, 9), range('A', 'Z'));
shuffle($chars);
$start = mt_rand(0, count($chars) - self::$nonce_length);
return substr(join('', $chars), $start, self::$nonce_length);
}
je duplique 10 fois le tableau[0-9, A-Z] et mélange les éléments, après avoir obtenu un point de départ aléatoire pour que substr () soit plus "créatif" :) vous pouvez ajouter [A-z] et d'autres éléments à array, dupliquer plus ou moins, être plus créatif que moi
voici ce que j'utilise sur un de mes projets, il fonctionne très bien et il génère un jeton aléatoire UNIQUE :
$timestampz=time();
function generateRandomString($length = 60) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$tokenparta = generateRandomString();
$token = $timestampz*3 . $tokenparta;
echo $token;
veuillez noter que j'ai multiplié l'horodatage par trois pour créer une confusion pour celui qui pourrait se demander comment ce token est généré;)
j'espère que cela aide :)
je pense que c'est la meilleure méthode à utiliser.
str_shuffle(md5(rand(0,100000)))
<?php
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>
la fonction ci-dessus vous générera une chaîne de caractères aléatoire d'une longueur de 11 caractères.
nous pouvons utiliser cette Deux Ligne de code pour générer une chaîne unique ont testé environ 10000000 fois d'itération
$sffledStr= str_shuffle('abscdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+');
$uniqueString = md5(time().$sffledStr);
pour les chaînes vraiment aléatoires, vous pouvez utiliser
<?php
echo md5(microtime(true).mt_Rand());
sorties:
40a29479ec808ad4bcff288a48a25d5c
donc même si vous essayez de générer de la chaîne de caractères plusieurs fois au même moment, vous obtiendrez une sortie différente.
c'est une fonction simple qui vous permet de générer des chaînes aléatoires contenant des Lettres et des nombres (alphanumériques). Vous pouvez également limiter la longueur de la chaîne. Ces chaînes aléatoires peuvent être utilisées à diverses fins, y compris: le code de référence, le Code promotionnel, le code de Coupon. La fonction s'appuie sur les fonctions PHP suivantes: base_convert, sha1, uniqid, la fonction mt_rand
function random_code($length)
{
return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}
echo random_code(6);
/*sample output
* a7d9e8
* 3klo93
*/
je crois que le problème avec toutes les idées existantes est qu'elles sont probablement unique, mais pas certainement unique (comme souligné dans la réponse de Dariusz Walczak à loletech). J'ai une solution qui est vraiment unique. Il faut que votre script ait une sorte de mémoire. Pour moi, c'est une base de données SQL. Vous pouvez aussi simplement écrire dans un fichier quelque part. Il y a deux implémentations:
première méthode: avoir deux champs plutôt que 1 qui fournissent un caractère unique. Le premier champ est un numéro D'identification qui n'est pas aléatoire mais unique (le premier ID est 1, le second 2...). Si vous utilisez SQL, définissez simplement le champ ID avec la propriété AUTO_ incrément. Le second champ n'est pas unique mais aléatoire. Cela peut être généré avec n'importe laquelle des autres techniques que les gens ont déjà mentionnées. L'idée de Scott était bonne, mais md5 est pratique et probablement assez bonne pour la plupart des buts:
$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());
Second méthode: fondamentalement la même idée, mais d'abord choisir un nombre maximum de chaînes qui ne seront jamais générés. Cela pourrait être juste un très grand nombre comme un billion de dollars. Ensuite, faire la même chose, générer un ID, mais zéro le pad de sorte que tous les ID sont le même nombre de chiffres. Alors concaténez L'ID avec la chaîne aléatoire. Il sera assez aléatoire pour la plupart des fins, mais la section ID veillera à ce qu'il soit également unique.
vous pouvez utiliser ce code, J'espère que ce sera utile pour vous.
function rand_code($len)
{
$min_lenght= 0;
$max_lenght = 100;
$bigL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$smallL = "abcdefghijklmnopqrstuvwxyz";
$number = "0123456789";
$bigB = str_shuffle($bigL);
$smallS = str_shuffle($smallL);
$numberS = str_shuffle($number);
$subA = substr($bigB,0,5);
$subB = substr($bigB,6,5);
$subC = substr($bigB,10,5);
$subD = substr($smallS,0,5);
$subE = substr($smallS,6,5);
$subF = substr($smallS,10,5);
$subG = substr($numberS,0,5);
$subH = substr($numberS,6,5);
$subI = substr($numberS,10,5);
$RandCode1 = str_shuffle($subA.$subD.$subB.$subF.$subC.$subE);
$RandCode2 = str_shuffle($RandCode1);
$RandCode = $RandCode1.$RandCode2;
if ($len>$min_lenght && $len<$max_lenght)
{
$CodeEX = substr($RandCode,0,$len);
}
else
{
$CodeEX = $RandCode;
}
return $CodeEX;
}
détails sur générateur de code aléatoire en PHP
simplifier le code Scotts ci-dessus en supprimant les boucles inutiles qui ralentissent mal et ne le rend pas plus sûr que d'appeler openssl_random_pseudo_bytes juste une fois
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(log($range, 2));
$bytes = (int) ($log / 8) + 1; // length in bytes
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
return $min + $rnd%$range;
}
function getToken($length)
{
return bin2hex(openssl_random_pseudo_bytes($length)
}