我只是在研究如何解决相同的问题,但是我也希望我的函数创建一个令牌,该令牌也可以用于密码检索。这意味着我需要限制令牌被猜测的能力。因为uniqid
基于时间,并且根据php.net“返回值与microtime()几乎没有区别”,uniqid
所以不符合标准。PHP建议openssl_random_pseudo_bytes()
改为使用来生成加密安全令牌。
一个快速,简短而切题的答案是:
bin2hex(openssl_random_pseudo_bytes($bytes))
它将生成一个随机字符串,由长度为$ bytes * 2的字母数字字符组成。不幸的是,它只有一个字母[a-f][0-9]
,但是可以使用。
以下是我可以满足标准的最强大功能(这是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)
用作rand()
或的替代品mt_rand
。它使用openssl_random_pseudo_bytes帮助创建介于$ min和$ max之间的随机数。
getToken($length)
创建在令牌中使用的字母,然后创建一个长度的字符串$length
。
编辑:我忽略了引用源-http: //us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
编辑(PHP7):随着PHP7的发布,标准库现在具有两个新功能,可以替换/改进/简化上面的crypto_rand_secure函数。random_bytes($length)
和random_int($min, $max)
http://php.net/manual/zh/function.random-bytes.php
http://php.net/manual/zh/function.random-int.php
例:
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;
}