如何生成随机、唯一、字母数字结合的字符串?
如何生成随机、唯一、字母数字结合的字符串?
如何使用数字和字母生成一个随机、唯一的字符串,用于验证链接?就像在网站上创建帐户时,它会向您发送一封电子邮件,其中包含一个链接,您必须点击该链接以验证您的帐户。
我该如何使用PHP生成这样的链接?
安全提示: 不应在随机数的质量可能影响应用程序安全的情况下使用此解决方案。特别是,
rand()
和uniqid()
不是密码学安全的随机数生成器。请参考Scott's answer,获取安全可靠的替代方案。
如果不需要它在时间上是绝对唯一的:
md5(uniqid(rand(), true))
否则 (假设您已经确定了用户的唯一登录名):
md5(uniqid($your_user_login, true))
PHP 7 标准库提供了 random_bytes($length)
函数,它生成了密码学安全的伪随机字节。
例如:
$bytes = random_bytes(20); var_dump(bin2hex($bytes));
上面的例子将输出类似以下的内容:
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
更多信息: http://php.net/manual/en/function.random-bytes.php
PHP 5 (已过时)
我刚刚看到如何解决这个问题,但是我还希望我的函数可以创建可用于密码检索的令牌。这意味着我需要限制令牌被猜测的能力。因为 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