Estaba buscando cómo resolver este mismo problema, pero también quiero que mi función cree un token que también se pueda usar para recuperar la contraseña. Esto significa que necesito limitar la capacidad del token para ser adivinado. Debido a que uniqid
se basa en el tiempo, y de acuerdo con php.net "el valor de retorno es un poco diferente de microtime ()", uniqid
no cumple con los criterios. PHP recomienda usar en su openssl_random_pseudo_bytes()
lugar para generar tokens criptográficamente seguros.
Una respuesta rápida, breve y directa es:
bin2hex(openssl_random_pseudo_bytes($bytes))
que generará una cadena aleatoria de caracteres alfanuméricos de longitud = $ bytes * 2. Desafortunadamente, esto solo tiene un alfabeto de [a-f][0-9]
, pero funciona.
A continuación se muestra la función más potente que podría hacer que satisfaga los criterios (esta es una versión implementada de la respuesta de 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)
funciona como una caída en reemplazo de rand()
o mt_rand
. Utiliza openssl_random_pseudo_bytes para ayudar a crear un número aleatorio entre $ min y $ max.
getToken($length)
crea un alfabeto para usar dentro del token y luego crea una cadena de longitud $length
.
EDITAR: Olvidé citar la fuente: http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
EDITAR (PHP7): con el lanzamiento de PHP7, la biblioteca estándar ahora tiene dos nuevas funciones que pueden reemplazar / mejorar / simplificar la función crypto_rand_secure anterior. random_bytes($length)
yrandom_int($min, $max)
http://php.net/manual/en/function.random-bytes.php
http://php.net/manual/en/function.random-int.php
Ejemplo:
function getToken($length){
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
$max = strlen($codeAlphabet);
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[random_int(0, $max-1)];
}
return $token;
}