Tôi chỉ xem xét cách giải quyết vấn đề tương tự, nhưng tôi cũng muốn chức năng của mình tạo ra một mã thông báo có thể được sử dụng để truy xuất mật khẩu. Điều này có nghĩa là tôi cần hạn chế khả năng đoán mã thông báo. Bởi vì uniqid
dựa trên thời gian và theo php.net, "giá trị trả về hơi khác so với microtime ()", uniqid
không đáp ứng các tiêu chí. PHP khuyên bạn nên sử dụng openssl_random_pseudo_bytes()
thay vì tạo mã thông báo bảo mật bằng mật mã.
Câu trả lời nhanh, ngắn gọn và chính xác là:
bin2hex(openssl_random_pseudo_bytes($bytes))
sẽ tạo ra một chuỗi ký tự chữ và số ngẫu nhiên có độ dài = $ byte * 2. Thật không may, cái này chỉ có một bảng chữ cái [a-f][0-9]
, nhưng nó hoạt động.
Dưới đây là chức năng mạnh nhất tôi có thể thực hiện để đáp ứng các tiêu chí (Đây là phiên bản được thực hiện của câu trả lời của 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)
hoạt động như một sự thay thế cho rand()
hoặc mt_rand
. Nó sử dụng openssl_random_pseudo_bytes để giúp tạo một số ngẫu nhiên trong khoảng từ $ min đến $ max.
getToken($length)
tạo một bảng chữ cái để sử dụng trong mã thông báo và sau đó tạo một chuỗi độ dài $length
.
EDIT: Tôi đã bỏ qua việc trích dẫn nguồn - http://us1.php.net/manual/en/feft.openssl-random-pseudo-bytes.php#104322
EDIT (PHP7): Với việc phát hành PHP7, thư viện chuẩn hiện có hai chức năng mới có thể thay thế / cải thiện / đơn giản hóa chức năng crypto_rand_secure ở trên. random_bytes($length)
vàrandom_int($min, $max)
http://php.net/manual/en/feft.random-bytes.php
http://php.net/manual/en/feft.random-int.php
Thí dụ:
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;
}