Właśnie zastanawiałem się, jak rozwiązać ten sam problem, ale chcę również, aby moja funkcja utworzyła token, którego można również użyć do odzyskiwania hasła. Oznacza to, że muszę ograniczyć możliwość odgadnięcia tokena. Ponieważ uniqid
jest oparty na czasie i według php.net „zwracana wartość niewiele różni się od microtime ()”, uniqid
nie spełnia kryteriów. PHP zaleca używanie openssl_random_pseudo_bytes()
zamiast tego do generowania bezpiecznych kryptograficznie tokenów.
Szybka, krótka i konkretna odpowiedź brzmi:
bin2hex(openssl_random_pseudo_bytes($bytes))
który wygeneruje losowy ciąg znaków alfanumerycznych o długości = $ bajtów * 2. Niestety ma to tylko alfabet [a-f][0-9]
, ale działa.
Poniżej znajduje się najsilniejsza funkcja, jaką mogę wykonać, która spełnia kryteria (Jest to zaimplementowana wersja odpowiedzi Erika).
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)
działa jako kropla zastępująca dla rand()
lub mt_rand
. Używa openssl_random_pseudo_bytes, aby pomóc utworzyć losową liczbę między $ min a $ max.
getToken($length)
tworzy alfabet do użycia w tokenie, a następnie tworzy ciąg długości $length
.
EDYCJA: Zaniedbałem cytować źródło - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
EDYCJA (PHP7): Wraz z wydaniem PHP7 biblioteka standardowa ma teraz dwie nowe funkcje, które mogą zastąpić / ulepszyć / uprościć powyższą funkcję crypto_rand_secure. random_bytes($length)
irandom_int($min, $max)
http://php.net/manual/en/function.random-bytes.php
http://php.net/manual/en/function.random-int.php
Przykład:
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;
}