如何使用数字和字母生成一个随机且唯一的字符串用于验证链接?就像在网站上创建账户并通过电子邮件发送带有链接的邮件,您需要点击该链接以验证您的账户一样。
我如何使用PHP生成此类字符串?
如何使用数字和字母生成一个随机且唯一的字符串用于验证链接?就像在网站上创建账户并通过电子邮件发送带有链接的邮件,您需要点击该链接以验证您的账户一样。
我如何使用PHP生成此类字符串?
random_bytes($length)
函数,用于生成具有密码学安全性的伪随机字节。$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
uniqid
是基于时间的,而根据php.net的说法“返回值与microtime()略有不同”,uniqid
不符合要求。PHP建议使用openssl_random_pseudo_bytes()
来生成具有密码学安全性的令牌。bin2hex(openssl_random_pseudo_bytes($bytes))
[a-f][0-9]
,但它能正常工作。
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
的字符串。
来源:https://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
base64_encode
代替bin2hex
来得到一个字母表更大、字符串更短的编码。 - erjiang安全提示:本解决方案不应在随机性质量可能影响应用程序安全性的情况下使用。特别是,
rand()
和uniqid()
不是加密安全随机数生成器。请参阅Scott的答案以获取安全替代方案。
如果您不需要它在时间上是绝对唯一的:
md5(uniqid(rand(), true))
否则(假设您已经确定了用户的唯一登录):
md5(uniqid($your_user_login, true))
我根据Scott的答案创建了一个面向对象的解决方案:
<?php
namespace Utils;
/**
* Class RandomStringGenerator
* @package Utils
*
* Solution taken from here:
* https://dev59.com/1HI-5IYBdhLWcg3wc3-w#13733588
*/
class RandomStringGenerator
{
/** @var string */
protected $alphabet;
/** @var int */
protected $alphabetLength;
/**
* @param string $alphabet
*/
public function __construct($alphabet = '')
{
if ('' !== $alphabet) {
$this->setAlphabet($alphabet);
} else {
$this->setAlphabet(
implode(range('a', 'z'))
. implode(range('A', 'Z'))
. implode(range(0, 9))
);
}
}
/**
* @param string $alphabet
*/
public function setAlphabet($alphabet)
{
$this->alphabet = $alphabet;
$this->alphabetLength = strlen($alphabet);
}
/**
* @param int $length
* @return string
*/
public function generate($length)
{
$token = '';
for ($i = 0; $i < $length; $i++) {
$randomKey = $this->getRandomInteger(0, $this->alphabetLength);
$token .= $this->alphabet[$randomKey];
}
return $token;
}
/**
* @param int $min
* @param int $max
* @return int
*/
protected function getRandomInteger($min, $max)
{
$range = ($max - $min);
if ($range < 0) {
// Not so random...
return $min;
}
$log = log($range, 2);
// Length in bytes.
$bytes = (int) ($log / 8) + 1;
// Length in bits.
$bits = (int) $log + 1;
// Set all lower bits to 1.
$filter = (int) (1 << $bits) - 1;
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
// Discard irrelevant bits.
$rnd = $rnd & $filter;
} while ($rnd >= $range);
return ($min + $rnd);
}
}
<?php
use Utils\RandomStringGenerator;
// Create new instance of generator class.
$generator = new RandomStringGenerator;
// Set token length.
$tokenLength = 32;
// Call method to generate random string.
$token = $generator->generate($tokenLength);
如果需要,您可以使用自定义字母表。 只需将包含支持字符的字符串传递到构造函数或设置器中即可:
<?php
$customAlphabet = '0123456789ABCDEF';
// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);
// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);
SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
希望这能帮助到别人。干杯!
$obj = new RandomStringGenerator;
了,但是应该调用哪个方法呢?谢谢。 - sg552generate
方法。只需传递一个整数作为参数,以指定生成字符串的长度。 - Slava Fomin II我根据Scott的回答提供的功能,提供了一些良好的研究数据。因此,我为这个5天长的自动化测试设置了一个Digital Ocean droplet,并将生成的唯一字符串存储在MySQL数据库中。
在这个测试期间,我使用了5个不同的长度(5、10、15、20、50),每个长度插入了+/-0.5百万条记录。在我的测试中,只有长度为5的字符串生成了+/-3K重复项(在50万项中),其余长度没有生成任何重复项。因此,我们可以说,如果我们使用长度为15或以上的Scott函数,则可以生成高度可靠的唯一字符串。下面是显示我的研究数据的表格:
我创建了一个简单的Heroku应用程序,使用这些函数作为JSON响应返回令牌。该应用程序可以通过https://uniquestrings.herokuapp.com/api/token?length=15访问。
microtime()
无法生成具有密码学安全性的字符串,如果涉及到安全问题,我们不能依赖它们。 - Rehmatfunction generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0x0C2f ) | 0x4000,
mt_rand( 0, 0x3fff ) | 0x8000,
mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
);
}
//调用函数
$transationID = generate_uuid();
一些示例输出可能如下:
E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2
希望它能帮助未来的某个人 :)
该函数将使用数字和字母生成随机密钥:
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
echo random_string(50);
示例输出:
zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
我使用这个一行代码:
base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
其中length是所需字符串的长度(必须为4的倍数,否则将被舍入为最接近的能被4整除的数字)
==
这样的字符。 - user3459110base64url_encode
,请参见此处:http://php.net/manual/en/function.base64-encode.php - Paul使用以下代码生成11个字符的随机数,或根据您的要求更改数字。
$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
或者我们可以使用自定义函数生成随机数。
function randomNumber($length){
$numbers = range(0,9);
shuffle($numbers);
for($i = 0;$i < $length;$i++)
$digits .= $numbers[$i];
return $digits;
}
//generate random number
$randomNum=randomNumber(11);
substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstvwxyz', 36)), 0, 11);
。 - Tim Hallman对于真正随机的字符串,可以使用
<?php
echo md5(microtime(true).mt_Rand());
输出:
40a29479ec808ad4bcff288a48a25d5c
例如(伪代码)
int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough
uniqid
是不安全的。使用类似于Random::alphanumericString($length)
或者Random::alphanumericHumanString($length)
这样的东西。 - caw